home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / applic / ntp / kent.msg < prev    next >
Encoding:
Text File  |  1991-09-29  |  99.2 KB  |  3,333 lines

  1. 
  2. Received: from louie.udel.edu by huey.udel.edu id ab24775; 4 May 89 12:17 EDT
  3. Received: from ccv.bbn.com by louie.udel.edu id aa09055; 4 May 89 12:14 EDT
  4. Date:     Thu, 4 May 89 12:10:52 EDT
  5. From:     Steve Kent <kent@bbn.com>
  6. To:       Mills@udel.edu
  7. Subject:  Re:  DES routines
  8. Message-ID:  <8905041214.aa09055@louie.udel.edu>
  9.  
  10. Dave,
  11.  
  12.     Pardon the lateness, but as I mentioned before John
  13. Linn left in March and it's taking some time to regroup and
  14. find where various things are (though John did do an excellent
  15. job of organizing stuff and letting us know the state of the
  16. world before he left).  I've enclosed some c routines for DES and
  17. DES key schedule construction.  ZIHHIf you want the faster MC68K
  18. versions I could provide them too.  I also understand that the
  19. next BSD release will contain code that is much faster than the
  20. current "crypt" and the code contains elements of the speedups which
  21. are present in these routines.  Let me know if you have any problems
  22. with this code and how well it performs for your application.
  23.  
  24.     I will ask the PTF members to review your NTP authentication
  25. paper during our next meeting, so I can get back to you with
  26. comments by the beginning of June (if I don't get to it myself
  27. prior to then).
  28.  
  29. Steve
  30. ------------------------
  31. /* ----------------------------------------------------------------- */
  32. /* This DES software was developed by Steve Kent and John Linn       */
  33. /* of BBN Communications Corporation, Cambridge, MA                  */
  34. /* Do not redistribute this software, or integrate with other        */
  35. /* software, without preserving this notice                          */
  36. /* ----------------------------------------------------------------- */
  37.  
  38. /* ksb.c -- John Linn, 21 April 1983 --
  39.    This program uses an optimized, table-driven method to compute a
  40.    DES key schedule from 8 input bytes.
  41.    Once the optimizing table (pc2otab) has been computed, generation
  42.    of a schedule takes approximately 12 user ms on a C/70.
  43.  
  44.    Note: there is still room to optimize pc1 and tweak out a couple
  45.    of extra milliseconds from the key schedule build, but this
  46.    should only be important if and when adaptation to an environment
  47.    which needs to dynamically change keys is considered.
  48.  
  49.    21 Apr. -- removed c30 special case. c30 now takes same key format,
  50.    and output is always to file 'ks'.
  51.  
  52.    6 May -- added command line option to specify name of output file.
  53.    if no command arg, output is still to 'ks'.
  54.  
  55. */
  56.  
  57. #include <stdio.h>
  58.  
  59. /* tables to describe permutations, per NBS FIPS */
  60.  
  61. static int pc1c [] =
  62.     { 57, 49, 41, 33, 25, 17, 9,
  63.       1, 58, 50, 42, 34, 26, 18,
  64.       10, 2, 59, 51, 43, 35, 27,
  65.       19, 11, 3, 60, 52, 44, 36 };
  66.  
  67. static int pc1d [] =
  68.     { 63, 55, 47, 39, 31, 23, 15,
  69.       7, 62, 54, 46, 38, 30, 22,
  70.       14, 6, 61, 53, 45, 37, 29,
  71.       21, 13, 5, 28, 20, 12, 4 };
  72.  
  73. static int shiftsked []=
  74.     { 1, 1, 2, 2, 2, 2, 2, 2,
  75.       1, 2, 2, 2, 2, 2, 2, 1 };
  76.  
  77. static int pc2 [] =
  78.     { 14, 17, 11, 24, 1, 5,
  79.       3, 28, 15, 6, 21, 10,
  80.       23, 19, 12, 4, 26, 8,
  81.       16, 7, 27, 20, 13, 2,
  82.       41, 52, 31, 37, 47, 55,
  83.       30, 40, 51, 45, 33, 48,
  84.       44, 49, 39, 56, 34, 53,
  85.       46, 42, 50, 36, 29, 32 };
  86.  
  87. /* --- some bit manipulation primitives --- */
  88.  
  89. /* g_keybit -- extract bit bnum from the key in inkey */
  90. #define g_keybit(bnum) (01 & (inkey [bnum/8] >> (8 - (bnum%8))))
  91.  
  92. long    lrot28 (lval)
  93. /* do left rotate of 28 bit quantity */
  94. long    lval;
  95. {
  96.   lval <<= 1;
  97.   if (0X10000000L & lval) lval++;
  98.   lval &= 0XFFFFFFFL;
  99.   return (lval);
  100. }
  101.  
  102. /* --- following code and data does key schedule generation --- */
  103.  
  104. unsigned skedkeys [16] [4];
  105.  
  106. unsigned inkey [8];     /* input key goes here */
  107.  
  108. long pc2otab [8] [128]; /* table to optimize pc2 */
  109.  
  110. spc2otab ()     /* initialize pc2otab for pc2 lookups */
  111. {
  112. #define NOTSEL  -1
  113.  
  114.   extern long pc2otab [8] [128];
  115.   extern int pc2 [48];
  116.   
  117.   int bn, bv, bitloc, i;
  118.   int bitindx [7];
  119.  
  120.   for (bn = 0; bn < 8; bn++)    /* each input 7-bit byte, l->r */
  121.   {
  122.     for (i = 0; i < 7; i++)     /* find each bit in the byte */
  123.     {
  124.     /* determine where (or if) pc2 places the given bit in the
  125.        output.  set bitindx [0] to the bit number (1->48,l->r)
  126.        where the MSB of the byte occurs, or to NOTSEL if pc2
  127.        doesn't pick it. similar down through bitindx [6]. */
  128.  
  129.       for (bitloc = 0; bitloc < 48; bitloc++)
  130.       {
  131.     /* trying until a match in pc2 found or table exhausted */
  132.         if (pc2 [bitloc] == (1 + ((bn * 7) + i)))
  133.         {
  134.           bitindx [i] = bitloc + 1;
  135.           break;
  136.         } 
  137.       }
  138.       if (bitloc == 48) bitindx [i] = NOTSEL;
  139.     }
  140.  
  141.     for (bv = 0; bv < 128; bv++)
  142.     {
  143.       /* setting up a table entry for each input byte value */
  144.       pc2otab [bn] [bv] = 0L;
  145.       if (bn < 4)       /* this is left word (nbs bits 1-24) */
  146.       {
  147.     for (i = 0; i < 7; i++)
  148.     {
  149.        if (NOTSEL == bitindx [i]) continue;
  150.         if (bv & (01 << (6 - i)))
  151.           pc2otab [bn] [bv] |= (0X1L << (24 - bitindx [i]));
  152.     }
  153.       }
  154.       else              /* this is right word (nbs bits 25-48) */
  155.       {
  156.     for (i = 0; i < 7; i++)
  157.     {
  158.           if (NOTSEL == bitindx [i]) continue;
  159.            if (bv & (01 << (6 - i)))
  160.              pc2otab [bn] [bv] |= (0X1L << (48 - bitindx [i]));
  161.     }
  162.       }
  163.     }
  164.   }
  165. }
  166.  
  167. ksmake ()       /* Make a key schedule from key bytes in inkey */
  168. {
  169.   extern unsigned skedkeys [16] [4];
  170.   extern long pc2otab [8] [128];
  171.  
  172.   int   round;
  173.   long  pcct, pcdt;
  174.   long  pc2out [2];
  175.   int   i;
  176.  
  177.   /* do pc-1 permutation, extracting bits from inkey */
  178.   pcct = pcdt = 0L;
  179.   for (i = 0; i < 27; i++)   
  180.    /* filling all appropriate bits */
  181.   {
  182.     pcct |= g_keybit(pc1c [i]);
  183.     pcdt |= g_keybit(pc1d [i]);
  184.     pcct <<= 1;
  185.     pcdt <<= 1;
  186.   }
  187.   /* one final ior, without a shift */
  188.   pcct |= g_keybit(pc1c [i]);
  189.   pcdt |= g_keybit(pc1d [i]);
  190.  
  191.   for (round = 0; round < 16; round++)
  192.   {
  193.     /* always at least one shift */
  194.     pcct = lrot28 (pcct);
  195.     pcdt = lrot28 (pcdt);
  196.  
  197.     if (shiftsked [round] == 2)
  198.     {   /* this round needs another shift */
  199.       pcct = lrot28 (pcct);
  200.       pcdt = lrot28 (pcdt);
  201.     } 
  202.  
  203.     /* Now, pcct and pcdt have the values on which we can apply
  204.        pc2 and select the key bits, storing them in pc2out[0] and
  205.        pc2out[1]. The high order [pc2out[0]] bits all come from
  206.        pcct, and the low order from pcdt. */
  207.  
  208.     pc2out [0] = pc2otab [0] [pcct >> 21];
  209.     pc2out [0] |= pc2otab [1] [0X7F & (pcct >> 14)];
  210.     pc2out [0] |= pc2otab [2] [0X7F & (pcct >> 7)];
  211.     pc2out [0] |= pc2otab [3] [0X7F & pcct];
  212.  
  213.     pc2out [1] = pc2otab [4] [pcdt >> 21];
  214.     pc2out [1] |= pc2otab [5] [0X7F & (pcdt >> 14)];
  215.     pc2out [1] |= pc2otab [6] [0X7F & (pcdt >> 7)];
  216.     pc2out [1] |= pc2otab [7] [0X7F & pcdt];
  217.  
  218.     /* order key bits and bytes so as to be compatible with
  219.        the format generated by the E implementation */
  220.  
  221.     skedkeys [round] [0] = 0XFC00 & (pc2out [0] >> 8);
  222.     skedkeys [round] [0] |= (0XFC & (pc2out [0] >> 4));
  223.     skedkeys [round] [1] = 0XFC00 & (pc2out [1] >> 8);
  224.     skedkeys [round] [1] |= (0XFC & (pc2out [1] >> 4));
  225.  
  226.     skedkeys [round] [2] = 0XFC00 & (pc2out [0] >> 2);
  227.     skedkeys [round] [2] |= (0XFC & (pc2out [0] << 2));
  228.     skedkeys [round] [3] = 0XFC00 & (pc2out [1] >> 2);
  229.     skedkeys [round] [3] |= (0XFC & (pc2out [1] << 2));
  230.   }
  231. }
  232.  
  233. int parval ()  /* test parity of key in inkey; return 1 iff OK */
  234. {
  235.   int i, j;
  236.   int parac;
  237.   unsigned incopy;
  238.  
  239.   for (i = 0; i < 8; i++)       /* do each byte */
  240.   {
  241.     parac = 0;
  242.     incopy = inkey [i];
  243.  
  244.     for (j = 0; j < 8; j++)     /* 8 bits in a DES byte */
  245.     {
  246.       if (incopy & 01) parac++;
  247.       incopy >>= 1;
  248.     }
  249.     if (! (parac & 01)) return (0); /* no odd parity on this byte */
  250.   }
  251.   return (1);   /* OK on all of them */
  252. }
  253.  
  254. /* main for ksb -- accept and validate key, output schedule */
  255. main (argc, argv)
  256. int     argc;
  257. char    *argv [];
  258. {
  259.   extern unsigned skedkeys [16] [4];
  260.   extern unsigned inkey [8];
  261.  
  262.   int i, j;
  263.   FILE * fp, *fopen ();
  264.  
  265.   spc2otab ();  /* compute internal table */
  266.  
  267.   printf ("Enter DES key as 8 hex bytes: ");
  268.   scanf ("%x %x %x %x %x %x %x %x",
  269.     &inkey [0], &inkey [1], &inkey [2], &inkey [3],
  270.     &inkey [4], &inkey [5], &inkey [6], &inkey [7]);
  271.  
  272.   if (! parval ())
  273.   {
  274.     printf ("Bad parity on key... aborting...\n");
  275.     exit (1);
  276.   }
  277.  
  278.   ksmake ();
  279.  
  280.   
  281.   if (NULL == (fp = fopen (((argc > 1) ? argv [1] : "ks"), "w")))
  282.   {
  283.     printf ("ksb -- can't open output file '%s'\n",
  284.      ((argc > 1) ? argv [1] : "ks"));
  285.     exit (1);
  286.   }
  287.   
  288.   for (i = 0; i < 16; i++)      /* output entire schedule to file */
  289.   {
  290.     for (j = 0; j < 4; j++)
  291.       /* format is xxxxxx00xxxxxx00 */
  292.       fprintf (fp, "%x\n", skedkeys [i] [j]);
  293.   }
  294.   
  295.   printf ("ksb -- key schedule output to file '%s'\n",
  296.    ((argc > 1) ? argv [1] : "ks"));
  297. }
  298.  
  299. /* modified 6 May 1983 to allow optional command arg which specifies
  300.    output file name. if no arg, output goes to file 'ks' */
  301.  
  302. #include <stdio.h>
  303.  
  304. /* tables to describe permutations, per NBS FIPS */
  305.  
  306. static int pc1c [] =
  307.     { 57, 49, 41, 33, 25, 17, 9,
  308.       1, 58, 50, 42, 34, 26, 18,
  309.       10, 2, 59, 51, 43, 35, 27,
  310.       19, 11, 3, 60, 52, 44, 36 };
  311.  
  312. static int pc1d [] =
  313.     { 63, 55, 47, 39, 31, 23, 15,
  314.       7, 62, 54, 46, 38, 30, 22,
  315.       14, 6, 61, 53, 45, 37, 29,
  316.       21, 13, 5, 28, 20, 12, 4 };
  317.  
  318. static int shiftsked []=
  319.     { 1, 1, 2, 2, 2, 2, 2, 2,
  320.       1, 2, 2, 2, 2, 2, 2, 1 };
  321.  
  322. static int pc2 [] =
  323.     { 14, 17, 11, 24, 1, 5,
  324.       3, 28, 15, 6, 21, 10,
  325.       23, 19, 12, 4, 26, 8,
  326.       16, 7, 27, 20, 13, 2,
  327.       41, 52, 31, 37, 47, 55,
  328.       30, 40, 51, 45, 33, 48,
  329.       44, 49, 39, 56, 34, 53,
  330.       46, 42, 50, 36, 29, 32 };
  331.  
  332. /* --- some bit manipulation primitives --- */
  333.  
  334. /* g_keybit -- extract bit bnum from the key in inkey */
  335. #define g_keybit(bnum) (01 & (inkey [bnum/8] >> (8 - (bnum%8))))
  336.  
  337. long    lrot28 (lval)
  338. /* do left rotate of 28 bit quantity */
  339. long    lval;
  340. {
  341.   lval <<= 1;
  342.   if (0X10000000L & lval) lval++;
  343.   lval &= 0XFFFFFFFL;
  344.   return (lval);
  345. }
  346.  
  347. /* --- following code and data does key schedule generation --- */
  348.  
  349. unsigned skedkeys [16] [4];
  350.  
  351. unsigned inkey [8];     /* input key goes here */
  352.  
  353. long pc2otab [8] [128]; /* table to optimize pc2 */
  354.  
  355. spc2otab ()     /* initialize pc2otab for pc2 lookups */
  356. {
  357. #define NOTSEL  -1
  358.  
  359.   extern long pc2otab [8] [128];
  360.   extern int pc2 [48];
  361.   
  362.   int bn, bv, bitloc, i;
  363.   int bitindx [7];
  364.  
  365.   for (bn = 0; bn < 8; bn++)    /* each input 7-bit byte, l->r */
  366.   {
  367.     for (i = 0; i < 7; i++)     /* find each bit in the byte */
  368.     {
  369.     /* determine where (or if) pc2 places the given bit in the
  370.        output.  set bitindx [0] to the bit number (1->48,l->r)
  371.        where the MSB of the byte occurs, or to NOTSEL if pc2
  372.        doesn't pick it. similar down through bitindx [6]. */
  373.  
  374.       for (bitloc = 0; bitloc < 48; bitloc++)
  375.       {
  376.     /* trying until a match in pc2 found or table exhausted */
  377.         if (pc2 [bitloc] == (1 + ((bn * 7) + i)))
  378.         {
  379.           bitindx [i] = bitloc + 1;
  380.           break;
  381.         } 
  382.       }
  383.       if (bitloc == 48) bitindx [i] = NOTSEL;
  384.     }
  385.  
  386.     for (bv = 0; bv < 128; bv++)
  387.     {
  388.       /* setting up a table entry for each input byte value */
  389.       pc2otab [bn] [bv] = 0L;
  390.       if (bn < 4)       /* this is left word (nbs bits 1-24) */
  391.       {
  392.     for (i = 0; i < 7; i++)
  393.     {
  394.        if (NOTSEL == bitindx [i]) continue;
  395.         if (bv & (01 << (6 - i)))
  396.           pc2otab [bn] [bv] |= (0X1L << (24 - bitindx [i]));
  397.     }
  398.       }
  399.       else              /* this is right word (nbs bits 25-48) */
  400.       {
  401.     for (i = 0; i < 7; i++)
  402.     {
  403.           if (NOTSEL == bitindx [i]) continue;
  404.            if (bv & (01 << (6 - i)))
  405.              pc2otab [bn] [bv] |= (0X1L << (48 - bitindx [i]));
  406.     }
  407.       }
  408.     }
  409.   }
  410. }
  411.  
  412. ksmake ()       /* Make a key schedule from key bytes in inkey */
  413. {
  414.   extern unsigned skedkeys [16] [4];
  415.   extern long pc2otab [8] [128];
  416.  
  417.   int   round;
  418.   long  pcct, pcdt;
  419.   long  pc2out [2];
  420.   int   i;
  421.  
  422.   /* do pc-1 permutation, extracting bits from inkey */
  423.   pcct = pcdt = 0L;
  424.   for (i = 0; i < 27; i++)   
  425.    /* filling all appropriate bits */
  426.   {
  427.     pcct |= g_keybit(pc1c [i]);
  428.     pcdt |= g_keybit(pc1d [i]);
  429.     pcct <<= 1;
  430.     pcdt <<= 1;
  431.   }
  432.   /* one final ior, without a shift */
  433.   pcct |= g_keybit(pc1c [i]);
  434.   pcdt |= g_keybit(pc1d [i]);
  435.  
  436.   for (round = 0; round < 16; round++)
  437.   {
  438.     /* always at least one shift */
  439.     pcct = lrot28 (pcct);
  440.     pcdt = lrot28 (pcdt);
  441.  
  442.     if (shiftsked [round] == 2)
  443.     {   /* this round needs another shift */
  444.       pcct = lrot28 (pcct);
  445.       pcdt = lrot28 (pcdt);
  446.     } 
  447.  
  448.     /* Now, pcct and pcdt have the values on which we can apply
  449.        pc2 and select the key bits, storing them in pc2out[0] and
  450.        pc2out[1]. The high order [pc2out[0]] bits all come from
  451.        pcct, and the low order from pcdt. */
  452.  
  453.     pc2out [0] = pc2otab [0] [pcct >> 21];
  454.     pc2out [0] |= pc2otab [1] [0X7F & (pcct >> 14)];
  455.     pc2out [0] |= pc2otab [2] [0X7F & (pcct >> 7)];
  456.     pc2out [0] |= pc2otab [3] [0X7F & pcct];
  457.  
  458.     pc2out [1] = pc2otab [4] [pcdt >> 21];
  459.     pc2out [1] |= pc2otab [5] [0X7F & (pcdt >> 14)];
  460.     pc2out [1] |= pc2otab [6] [0X7F & (pcdt >> 7)];
  461.     pc2out [1] |= pc2otab [7] [0X7F & pcdt];
  462.  
  463.     /* order key bits and bytes so as to be compatible with
  464.        the format generated by the E implementation */
  465.  
  466.     skedkeys [round] [0] = 0XFC00 & (pc2out [0] >> 8);
  467.     skedkeys [round] [0] |= (0XFC & (pc2out [0] >> 4));
  468.     skedkeys [round] [1] = 0XFC00 & (pc2out [1] >> 8);
  469.     skedkeys [round] [1] |= (0XFC & (pc2out [1] >> 4));
  470.  
  471.     skedkeys [round] [2] = 0XFC00 & (pc2out [0] >> 2);
  472.     skedkeys [round] [2] |= (0XFC & (pc2out [0] << 2));
  473.     skedkeys [round] [3] = 0XFC00 & (pc2out [1] >> 2);
  474.     skedkeys [round] [3] |= (0XFC & (pc2out [1] << 2));
  475.   }
  476. }
  477.  
  478. int parval ()  /* test parity of key in inkey; return 1 iff OK */
  479. {
  480.   int i, j;
  481.   int parac;
  482.   unsigned incopy;
  483.  
  484.   for (i = 0; i < 8; i++)       /* do each byte */
  485.   {
  486.     parac = 0;
  487.     incopy = inkey [i];
  488.  
  489.     for (j = 0; j < 8; j++)     /* 8 bits in a DES byte */
  490.     {
  491.       if (incopy & 01) parac++;
  492.       incopy >>= 1;
  493.     }
  494.     if (! (parac & 01)) return (0); /* no odd parity on this byte */
  495.   }
  496.   return (1);   /* OK on all of them */
  497. }
  498.  
  499. int tossbit ()      /* request and return a coin toss value */
  500. {
  501.   char inarr [10];
  502.  
  503.   for (;;)      /* infinite loop until acceptable result entered */
  504.   {
  505.     printf ("heads or tails? (h or t): ");
  506.     scanf ("%s", inarr);
  507.     if ((inarr [0] == 'h') || (inarr [0] == 'H')) return (1);
  508.     if ((inarr [0] == 't') || (inarr [0] == 'T')) return (0);
  509.     printf ("Input unacceptable! Enter 'h' or 't'\n");
  510.   }
  511. }
  512. coin_to_key ()  /* prompt for and accept coin tosses, build inkey */
  513. {
  514.   extern unsigned inkey [8];
  515.  
  516.   int kbyte, kbit, parchk, toss, tosstot;
  517.  
  518.   tosstot = 0;
  519.   for (kbyte = 0; kbyte < 8; kbyte++)
  520.   {
  521.     inkey [kbyte] = 0;
  522.     parchk = 0;                         /* parity accumulator */
  523.     for (kbit = 0; kbit < 7; kbit++)    /* get 7 real bits for byte */
  524.     {
  525.       toss = tossbit ();
  526.       inkey [kbyte] |= (01 << (7 - kbit)) * toss;
  527.       parchk += toss;
  528.       tosstot += toss;  /* keep track of how many ones */
  529.     }
  530.     inkey [kbyte] |= 01 * (0 == (parchk & 01));
  531.     printf ("key byte %d (parity adjusted) is %x\n", kbyte+1, inkey [kbyte]);
  532.   }
  533.   printf ("Entire key is: ");
  534.   for (kbyte = 0; kbyte < 8; kbyte++) printf ("%x ", inkey [kbyte]);
  535.   printf ("\n");
  536.   printf ("Of 56 tossed bits, %d were ones\n", tosstot);
  537. }
  538.  
  539. /* main for tosskey -- accept and validate key, output schedule */
  540. main (argc, argv)
  541. int     argc;
  542. char    *argv [];
  543. {
  544.   extern unsigned skedkeys [16] [4];
  545.  
  546.   int i, j;
  547.   FILE * fp, *fopen ();
  548.  
  549.   spc2otab ();
  550.  
  551.   printf ("Welcome to tosskey. Prepare your coin for use.\n");
  552.  
  553.   coin_to_key ();       /* get individual entries, compose inkey */
  554.  
  555.   if (! parval ())
  556.   {
  557.     printf ("Bad parity on key... aborting...\n");
  558.     exit (1);
  559.   }
  560.  
  561.   printf ("Computing key schedule...\n");
  562.   ksmake ();
  563.  
  564.   if (NULL == (fp = fopen (((argc > 1) ? argv [1] : "ks"), "w")))
  565.   {
  566.     printf ("tosskey -- can't open output file '%s'",
  567.      ((argc > 1) ? argv [1] : "ks"));
  568.     exit (1);
  569.   }
  570.   
  571.   for (i = 0; i < 16; i++)      /* output entire schedule to file */
  572.   {
  573.     for (j = 0; j < 4; j++)
  574.      /* output format is xxxxxx00xxxxxx00 */
  575.      fprintf (fp, "%x\n", skedkeys [i] [j]);
  576.   }
  577.   
  578.   printf ("tosskey -- key schedule output to file '%s'\n",
  579.    ((argc > 1) ? argv [1] : "ks"));
  580. }
  581. /* des.c -- this file contains an optimized C-based DES algorithm       */
  582. /* implementation.  Many loops are stretched out into straight-line code, */
  583. /* so this version is not particularly short, modular, or readable.  (size */
  584. /* as of 31 Aug 83:  7338+1426+6372 = 15136b = 035440b) However, it is */
  585. /* quick.  (A DES encryption times at approximately 7 user ms on a C/70) It */
  586. /* reads its key schedule and certain tables from files generated by */
  587. /* associated programs ksb.c and tblbld.c.  John Linn -- 8 April 1983 */
  588. /* "Bug" fix 17 Feb 1984 - insert masking so as to have E work on
  589.    32 bit machines with sign extension on right shifts (like Vax, 68k (?)) */
  590. /* observation: when compiled onto vax, takes only ~ 2.6 ms to encrypt */
  591.  
  592. #include <stdio.h>
  593. #define LMASK    0XFCFCFCFCL;
  594.  
  595. /* data structures to be read from files */
  596. static long ip [2] [256];     
  597. static long ipi [2] [256];
  598. static long snop [8] [64];
  599. unsigned ks [16] [4];
  600.  
  601. /* rdfiles -- reads filed info, returns 1 iff success, 0 otherwise */
  602. int rdfiles ()
  603. {
  604.   int i, j;
  605.   FILE *fp, *fopen ();
  606.  
  607.   if (NULL == (fp = fopen ("ip", "r")))
  608.   {
  609.     printf ("des -- can't read file 'ip'\n");
  610.     return (0);
  611.   }
  612.   for (i = 0; i < 2; i++)
  613.     for (j = 0; j < 256; j++) 
  614.       if (EOF == fscanf (fp, "%lx", &ip [i] [j]))
  615.       {
  616.         printf ("des -- 'ip' read failed at i=%d, j=%d\n", i, j);
  617.     return (0);
  618.       }
  619.   fclose (fp);
  620.   
  621.   if (NULL == (fp = fopen ("ipi", "r")))
  622.   {
  623.     printf ("des -- can't read file 'ipi'\n");
  624.     return (0);
  625.   }
  626.   for (i = 0; i < 2; i++)
  627.     for (j = 0; j < 256; j++) 
  628.       if (EOF == fscanf (fp, "%lx", &ipi [i] [j]))
  629.       {
  630.     printf ("des -- 'ipi' read failed at i=%d, j=%d\n", i, j);
  631.     return (0);
  632.       }
  633.   fclose (fp);
  634.   
  635.   if (NULL == (fp = fopen ("snop", "r")))
  636.   {
  637.     printf ("des -- can't read file 'snop'\n");
  638.     return (0);
  639.   }
  640.   for (i = 0; i < 8; i++)
  641.     for (j = 0; j < 64; j++) 
  642.       if (EOF == fscanf (fp, "%lx", &snop [i] [j]))
  643.       {
  644.         printf ("des -- 'snop' read failed at i=%d, j=%d\n", i, j);
  645.     return (0);
  646.       }
  647.   fclose (fp);
  648.  
  649.   if (NULL == (fp = fopen ("ks", "r")))
  650.   {
  651.     printf ("des -- can't read file 'ks'\n");
  652.     return (0);
  653.   }
  654.   for (i = 0; i < 16; i++)
  655.     for (j = 0; j < 4; j++) 
  656.       if (EOF == fscanf (fp, "%x", &ks [i] [j]))
  657.       {
  658.     printf ("des -- 'ks' read failed at i=%d, j=%d\n", i, j);
  659.     return (0);
  660.       }
  661.   fclose (fp);
  662.   
  663.   return (1);   /* success */
  664. }
  665.  
  666. #define BINBLK  8       /* number of bytes in an encryption chunk */
  667. #define BINLNG  4       /* the number of bytes in 32 bits of a long */
  668.  
  669. /* doip -- use ip table to permute 64 bits from inar to outar */
  670. doip (inar, outar)      
  671. long    inar [2];
  672. long    outar [2];
  673. {
  674.   extern long ip [2] [256];
  675.  
  676.   outar [0] = outar [1] = 0L;
  677.  
  678.   outar [0] |= ip [0] [0XFF & inar [1]];
  679.   outar [1] |= ip [1] [0XFF & inar [1]];
  680.   outar [0] <<= 1;
  681.   outar [1] <<= 1;
  682.   outar [0] |= ip [0] [0XFF & (inar [1] >> 8)];
  683.   outar [1] |= ip [1] [0XFF & (inar [1] >> 8)];
  684.   outar [0] <<= 1;
  685.   outar [1] <<= 1;
  686.   outar [0] |= ip [0] [0XFF & (inar [1] >> 16)];
  687.   outar [1] |= ip [1] [0XFF & (inar [1] >> 16)];
  688.   outar [0] <<= 1;
  689.   outar [1] <<= 1;
  690.   outar [0] |= ip [0] [0XFF & (inar [1] >> 24)];
  691.   outar [1] |= ip [1] [0XFF & (inar [1] >> 24)];
  692.   outar [0] <<= 1;
  693.   outar [1] <<= 1;
  694.   outar [0] |= ip [0] [0XFF & inar [0]];
  695.   outar [1] |= ip [1] [0XFF & inar [0]];
  696.   outar [0] <<= 1;
  697.   outar [1] <<= 1;
  698.   outar [0] |= ip [0] [0XFF & (inar [0] >> 8)];
  699.   outar [1] |= ip [1] [0XFF & (inar [0] >> 8)];
  700.   outar [0] <<= 1;
  701.   outar [1] <<= 1;
  702.   outar [0] |= ip [0] [0XFF & (inar [0] >> 16)];
  703.   outar [1] |= ip [1] [0XFF & (inar [0] >> 16)];
  704.   outar [0] <<= 1;
  705.   outar [1] <<= 1;
  706.   outar [0] |= ip [0] [0XFF & (inar [0] >> 24)];
  707.   outar [1] |= ip [1] [0XFF & (inar [0] >> 24)];
  708. }
  709.  
  710. /* doipi -- use ipi to perform ip-inverse */
  711. /* doesn't use ipis table: knowledge of byte order is hardcoded */
  712. doipi (inar, outar)     
  713. long    inar [2];
  714. long    outar [2];
  715. {
  716.   extern long ipi [2] [256];
  717.  
  718.   outar [0] = outar [1] = 0L;
  719.  
  720.   outar [0] |= ipi [0] [0XFF & (inar [1] >> 24)];       /* "5" */
  721.   outar [1] |= ipi [1] [0XFF & (inar [1] >> 24)];
  722.   outar [0] <<= 1;
  723.   outar [1] <<= 1;
  724.   outar [0] |= ipi [0] [0XFF & (inar [0] >> 24)];       /* "1" */
  725.   outar [1] |= ipi [1] [0XFF & (inar [0] >> 24)];
  726.   outar [0] <<= 1;
  727.   outar [1] <<= 1;
  728.   outar [0] |= ipi [0] [0XFF & (inar [1] >> 16)];       /* "6" */
  729.   outar [1] |= ipi [1] [0XFF & (inar [1] >> 16)];
  730.   outar [0] <<= 1;
  731.   outar [1] <<= 1;
  732.   outar [0] |= ipi [0] [0XFF & (inar [0] >> 16)];       /* "2" */
  733.   outar [1] |= ipi [1] [0XFF & (inar [0] >> 16)];
  734.   outar [0] <<= 1;
  735.   outar [1] <<= 1;
  736.   outar [0] |= ipi [0] [0XFF & (inar [1] >> 8)];        /* "7" */
  737.   outar [1] |= ipi [1] [0XFF & (inar [1] >> 8)];
  738.   outar [0] <<= 1;
  739.   outar [1] <<= 1;
  740.   outar [0] |= ipi [0] [0XFF & (inar [0] >> 8)];        /* "3" */
  741.   outar [1] |= ipi [1] [0XFF & (inar [0] >> 8)];
  742.   outar [0] <<= 1;
  743.   outar [1] <<= 1;
  744.   outar [0] |= ipi [0] [0XFF & inar [1]];       /* "8" */
  745.   outar [1] |= ipi [1] [0XFF & inar [1]];
  746.   outar [0] <<= 1;
  747.   outar [1] <<= 1;
  748.   outar [0] |= ipi [0] [0XFF & inar [0]];       /* "4" */
  749.   outar [1] |= ipi [1] [0XFF & inar [0]];
  750. }
  751.  
  752. /* des_encrypt -- encrypt a block under key sched in ks */
  753. des_encrypt (inar, outar)   
  754. long    inar [2];
  755. long    outar [2];
  756. {
  757.   extern unsigned ks [16] [4];
  758.   extern long snop [8] [64];
  759.  
  760.   register int round, oddbit;
  761.   unsigned expan [4];   /* receives output of E transform */
  762.   long sbout, scopy, tlong;
  763.   long oarr [2];
  764.  
  765.   doip (inar, outar);
  766.  
  767.   for (round = 0; round < 16; round++)
  768.   {
  769.     sbout = 0L;
  770.  
  771.     tlong = outar [1];
  772.     oddbit = (int) (01 & tlong);
  773.     tlong >>= 1;
  774.     tlong &= 0X7FFFFFFFL;       /* defeat sign extend -- jl 17 feb 84 */
  775.     if (oddbit) tlong |= 0X80000000L;
  776.  
  777.     tlong &= LMASK;
  778.     expan [0] = (unsigned) (tlong >> 16);
  779.     expan [1] = (unsigned) tlong;
  780.  
  781.     tlong = outar [1];
  782.     oddbit = !! (tlong & 0X80000000L);
  783.     tlong <<= 3;
  784.     if (oddbit) tlong |= 04;
  785.     tlong &= LMASK;
  786.     expan [2] = (unsigned) (tlong >> 16);
  787.     expan [3] = (unsigned) tlong;
  788.  
  789.     /* this code bypasses the alternative of loop setup 
  790.        and resultant computation within the loop for speed */
  791.     expan [0] ^= ks [round] [0];
  792.     sbout |= snop [0] [0X3F & (expan [0] >> 10)];
  793.     sbout |= snop [1] [0X3F & (expan [0] >> 2)];
  794.     expan [1] ^= ks [round] [1];
  795.     sbout |= snop [2] [0X3F & (expan [1] >> 10)];
  796.     sbout |= snop [3] [0X3F & (expan [1] >> 2)];
  797.     expan [2] ^= ks [round] [2];
  798.     sbout |= snop [4] [0X3F & (expan [2] >> 10)];
  799.     sbout |= snop [5] [0X3F & (expan [2] >> 2)];
  800.     expan [3] ^= ks [round] [3];
  801.     sbout |= snop [6] [0X3F & (expan [3] >> 10)];
  802.     sbout |= snop [7] [0X3F & (expan [3] >> 2)];
  803.  
  804.     scopy = outar [0];
  805.     outar [0] = outar [1];
  806.     outar [1] = scopy ^ sbout;
  807.   }
  808.  
  809.   /* a final swap */
  810.   scopy = outar [0];
  811.   outar [0] = outar [1];
  812.   outar [1] = scopy;
  813.  
  814.   doipi (outar, oarr);  /* perform ip-inverse into temp copy */
  815.   outar [0] = oarr [0];
  816.   outar [1] = oarr [1];
  817. }
  818.  
  819. /* des_decrypt -- decrypt a block under key sched in ks */
  820. des_decrypt (inar, outar)   
  821. long    inar [2];
  822. long    outar [2];
  823. {
  824.   extern unsigned ks [16] [4];
  825.   extern long snop [8] [64];
  826.  
  827.   register int round, oddbit;
  828.   unsigned expan [4];   /* receives output of E transform */
  829.   long sbout, scopy, tlong;
  830.   long oarr [2];
  831.  
  832.   doip (inar, outar);
  833.  
  834.   for (round = 15; round >= 0; round--)
  835.   /* note that decryption selects schedule keys in opposite order */
  836.   {
  837.     sbout = 0L;
  838.  
  839.     tlong = outar [1];
  840.     oddbit = (int) (01 & tlong);
  841.     tlong >>= 1;
  842.     tlong &= 0X7FFFFFFFL;       /* defeat sign extend -- jl 17 feb 84 */
  843.     if (oddbit) tlong |= 0X80000000L;
  844.  
  845.     tlong &= LMASK;
  846.     expan [0] = (unsigned) (tlong >> 16);
  847.     expan [1] = (unsigned) tlong;
  848.  
  849.     tlong = outar [1];
  850.     oddbit = !! (tlong & 0X80000000L);
  851.     tlong <<= 3;
  852.     if (oddbit) tlong |= 04;
  853.     tlong &= LMASK;
  854.     expan [2] = (unsigned) (tlong >> 16);
  855.     expan [3] = (unsigned) tlong;
  856.  
  857.     /* this code bypasses the alternative of loop setup 
  858.        and resultant computation within the loop for speed */
  859.     expan [0] ^= ks [round] [0];
  860.     sbout |= snop [0] [0X3F & (expan [0] >> 10)];
  861.     sbout |= snop [1] [0X3F & (expan [0] >> 2)];
  862.     expan [1] ^= ks [round] [1];
  863.     sbout |= snop [2] [0X3F & (expan [1] >> 10)];
  864.     sbout |= snop [3] [0X3F & (expan [1] >> 2)];
  865.     expan [2] ^= ks [round] [2];
  866.     sbout |= snop [4] [0X3F & (expan [2] >> 10)];
  867.     sbout |= snop [5] [0X3F & (expan [2] >> 2)];
  868.     expan [3] ^= ks [round] [3];
  869.     sbout |= snop [6] [0X3F & (expan [3] >> 10)];
  870.     sbout |= snop [7] [0X3F & (expan [3] >> 2)];
  871.  
  872.     scopy = outar [0];
  873.     outar [0] = outar [1];
  874.     outar [1] = scopy ^ sbout;
  875.   }
  876.  
  877.   /* a final swap */
  878.   scopy = outar [0];
  879.   outar [0] = outar [1];
  880.   outar [1] = scopy;
  881.  
  882.   doipi (outar, oarr);  /* perform ip-inverse into temp copy */
  883.   outar [0] = oarr [0];
  884.   outar [1] = oarr [1];
  885. }
  886.  
  887. /* facilities for timing */
  888. struct tbuffer
  889. {
  890.   long proc_utime;
  891.   long proc_stime;
  892.   long child_utime;
  893.   long child_stime;
  894. };
  895. struct tbuffer t_before;
  896. struct tbuffer t_after;
  897.  
  898. main ()
  899. {
  900.   int itnum, i;
  901.   long plain [2], crypt [2], cprbuf [2];
  902.   long udiff, bitsdone, u_msec;
  903.  
  904.   /* begin by reading tables and key schedule from files */
  905.   printf ("Reading filed tables and key schedule...\n");
  906.   if (1 != rdfiles ())
  907.   {
  908.     printf ("des -- couldn't get tables or key schedule\n");
  909.     exit (1);
  910.   }
  911.  
  912.   printf ("Enter input to encrypt as two hex longs: ");
  913.   scanf ("%lx %lx", &plain [0], &plain [1]);
  914.   des_encrypt (plain, crypt);
  915.   printf ("Result of encryption: %lx %lx\n", crypt [0], crypt [1]);
  916.  
  917.   printf ("Enter number of test iterations [decimal]: ");
  918.   scanf ("%d", &itnum);
  919.  
  920.   times (&t_before);
  921.   for (i = 0; i < itnum; i++)   
  922.   {
  923.     des_encrypt (plain, crypt);
  924.     des_decrypt (crypt, cprbuf);
  925.     if ((plain [0] != cprbuf [0]) || (plain [1] != cprbuf [1]))
  926.     {
  927.       printf ("Encrypt and decrypt disagree -- aborting!!\n");
  928.       exit (1);
  929.     }
  930.   }
  931.   times (&t_after);
  932.   printf ("All encryptions and decryptions verified consistent\n");
  933.  
  934.   /* note: the following code won't work if one times a number
  935.      of encryptions that take less than one tick, as can occur
  936.      on a vax with a small number of tests */
  937.   udiff = t_after.proc_utime - t_before.proc_utime;
  938.   printf ("user 1/60 sec ticks = %ld\n", udiff);
  939.   bitsdone = 2 * (itnum * 64);
  940.   u_msec = (udiff * 1000) / 60;
  941.   printf ("%ld user msec/DES cycle\n", u_msec / ((long) 2 * itnum));
  942.   printf ("%ld bits/user second\n", (bitsdone * 1000) / u_msec);
  943. }
  944.  
  945. /* slowdes.c --
  946.    this file contains a C-based DES algorithm implementation; the
  947.    version is modeled after the MBB implementation for
  948.    instructive clarity, and is not the most efficient version
  949.    available for the C/70.  It reads its key schedule and certain
  950.    tables from files generated by associated programs ksbuild.c
  951.    and tblbuild.c.  John Linn -- 4 March 1983 */
  952.    
  953. #include <stdio.h>
  954.  
  955. /* data structures to be read from files */
  956. static long ip [2] [256];     
  957. static long ipi [2] [256];
  958. static int ipis [8];
  959. static long snop [8] [64];
  960. unsigned ks [16] [4];
  961.  
  962. /* rdfiles -- reads filed info, returns 1 iff success, 0 otherwise */
  963. int rdfiles ()
  964. {
  965.   int i, j;
  966.   FILE *fp, *fopen ();
  967.  
  968.   if (NULL == (fp = fopen ("ip", "r")))
  969.   {
  970.     printf ("dodes -- can't read file 'ip'\n");
  971.     return (0);
  972.   }
  973.   for (i = 0; i < 2; i++)
  974.     for (j = 0; j < 256; j++) 
  975.       if (EOF == fscanf (fp, "%lx", &ip [i] [j]))
  976.       {
  977.         printf ("dodes -- 'ip' read failed at i=%d, j=%d\n", i, j);
  978.     return (0);
  979.       }
  980.   fclose (fp);
  981.   
  982.   if (NULL == (fp = fopen ("ipi", "r")))
  983.   {
  984.     printf ("dodes -- can't read file 'ipi'\n");
  985.     return (0);
  986.   }
  987.   for (i = 0; i < 2; i++)
  988.     for (j = 0; j < 256; j++) 
  989.       if (EOF == fscanf (fp, "%lx", &ipi [i] [j]))
  990.       {
  991.     printf ("dodes -- 'ipi' read failed at i=%d, j=%d\n", i, j);
  992.     return (0);
  993.       }
  994.   fclose (fp);
  995.   
  996.   if (NULL == (fp = fopen ("ipis", "r")))
  997.   {
  998.     printf ("dodes -- can't read file 'ipis'\n");
  999.     return (0);
  1000.   }
  1001.   for (i = 0; i < 8; i++) 
  1002.     if (EOF == fscanf (fp, "%x", &ipis [i]))
  1003.     {
  1004.       printf ("dodes -- 'ipis' read failed at i=%d\n");
  1005.       return (0);
  1006.     }     
  1007.   fclose (fp);
  1008.   
  1009.   if (NULL == (fp = fopen ("snop", "r")))
  1010.   {
  1011.     printf ("dodes -- can't read file 'snop'\n");
  1012.     return (0);
  1013.   }
  1014.   for (i = 0; i < 8; i++)
  1015.     for (j = 0; j < 64; j++) 
  1016.       if (EOF == fscanf (fp, "%lx", &snop [i] [j]))
  1017.       {
  1018.         printf ("dodes -- 'snop' read failed at i=%d, j=%d\n", i, j);
  1019.     return (0);
  1020.       }
  1021.   fclose (fp);
  1022.  
  1023.   if (NULL == (fp = fopen ("ks", "r")))
  1024.   {
  1025.     printf ("dodes -- can't read file 'ks'\n");
  1026.     return (0);
  1027.   }
  1028.   for (i = 0; i < 16; i++)
  1029.     for (j = 0; j < 4; j++) 
  1030.       if (EOF == fscanf (fp, "%x", &ks [i] [j]))
  1031.       {
  1032.     printf ("dodes -- 'ks' read failed at i=%d, j=%d\n", i, j);
  1033.     return (0);
  1034.       }
  1035.   fclose (fp);
  1036.   
  1037.   return (1);   /* success */
  1038. }
  1039.  
  1040. /* 
  1041.  
  1042. eexpand -- this routine performs a version of the DES E
  1043. transform, per Kent's algorithm for the MBB.  It accepts an input
  1044. long and returns its result in 4 words of an unsigned array,
  1045. ordered (1 3) (5 7) (2 4) (6 8).  Significant bits are left
  1046. justified in 8-bit bytes in these words:  the two low order bits
  1047. will always be zeroes.  This version is coded for clarity of
  1048. correspondence to the C/30 MBB version, not taking much advantage
  1049. of 32-bit operations.
  1050.  
  1051. */
  1052.  
  1053. #define MASK    0XFCFC;
  1054.  
  1055. eexpand (inlong, outarr)
  1056. long            inlong;
  1057. unsigned        outarr [];
  1058. {
  1059.   unsigned rega, regb, regc, regd;
  1060.   int oddbith, oddbitl, i;
  1061.  
  1062.   rega = regc = (unsigned) (0XFFFFL & (inlong >> 16));  /* high bits */
  1063.   regb = regd = (unsigned) (0XFFFFL & inlong);          /* low bits */
  1064.  
  1065.   /* rotate regc-regd pair right one */
  1066.   oddbith = !! (regc & 01);
  1067.   oddbitl = !! (regd & 01);
  1068.   regc >>= 1;
  1069.   regd >>= 1;
  1070.   if (oddbitl) regc |= 0X8000;
  1071.   if (oddbith) regd |= 0X8000;
  1072.  
  1073.   /* kill unused bits */
  1074.   regc &= MASK;
  1075.   regd &= MASK;
  1076.  
  1077.   /* rotate rega-regb pair left by three */
  1078.   for (i = 0; i < 3; i++)
  1079.   {
  1080.     oddbith = !! (rega & 0X8000);
  1081.     oddbitl = !! (regb & 0X8000);
  1082.     rega <<= 1;
  1083.     regb <<= 1;
  1084.     if (oddbitl) rega |= 01;
  1085.     if (oddbith) regb |= 01;
  1086.   }
  1087.  
  1088.   /* kill unused bits */
  1089.   rega &= MASK;
  1090.   regb &= MASK;
  1091.  
  1092.   outarr [0] = regc;
  1093.   outarr [1] = regd;
  1094.   outarr [2] = rega;
  1095.   outarr [3] = regb;
  1096. }
  1097.  
  1098. #define BINBLK  8       /* number of bytes in an encryption chunk */
  1099. #define BINLNG  4       /* the number of bytes in 32 bits of a long */
  1100.  
  1101. /* doip -- use ip table to permute 64 bits from inar to outar */
  1102. doip (inar, outar)      
  1103. long    inar [2];
  1104. long    outar [2];
  1105. {
  1106.   extern long ip [2] [256];
  1107.  
  1108.   int i,j;
  1109.  
  1110.   outar [0] = outar [1] = 0L;
  1111.  
  1112.   for (i = 0; i < BINBLK; i++)  /* input is 8 bytes */
  1113.                 /* msb of inar [0] ... lsb of inar [1] */
  1114.   {
  1115.     for (j = 0; j < 2; j++)     /* scan from r -> l */
  1116.       outar [j] |= ip [j] [0XFF & ((i < BINLNG) ?
  1117.             ((int) ((inar [1] >> (i * 8)))) :
  1118.             ((int) ((inar [0] >> ((i - BINLNG) * 8)))) )];
  1119.  
  1120.     if (i == (BINBLK - 1)) break;     /* don't shift an extra time */
  1121.  
  1122.     for (j = 0; j < 2; j++) outar [j] <<= 1;
  1123.   }
  1124. }
  1125.  
  1126. /* doipi -- use ipi, ipis to perform ip-inverse */
  1127. doipi (inar, outar)     
  1128. long    inar [2];
  1129. long    outar [2];
  1130. {
  1131.   extern int ipis [8];
  1132.   extern long ipi [2] [256];
  1133.  
  1134.   int i, j, bp;
  1135.  
  1136.   outar [0] = outar [1] = 0L;
  1137.  
  1138.   for (i = 0; i < BINBLK; i++)  /* input is 8 bytes */
  1139.   {
  1140.     bp = ipis [i] - 1;  /* translate byte indexes to zero origin */
  1141.  
  1142.     for (j = 0; j < 2; j++)
  1143.       outar [j] |= ipi [j] [0XFF & ((bp < BINLNG) ?
  1144.             ((int) (inar [0] >> (((BINLNG - bp) - 1) * 8))) :
  1145.             ((int) (inar [1] >> (((BINLNG - (bp-4)) - 1) * 8))) )];
  1146.  
  1147.     if (i == (BINBLK - 1)) break;
  1148.  
  1149.     for (j = 0; j < 2; j++) outar [j] <<= 1;
  1150.   }
  1151. }
  1152.  
  1153. /* des_encrypt -- encrypt a block under key sched in ks */
  1154. des_encrypt (inar, outar)   
  1155. long    inar [2];
  1156. long    outar [2];
  1157. {
  1158.   extern unsigned ks [16] [4];
  1159.   extern long snop [8] [64];
  1160.  
  1161.   int round, i, j;
  1162.   unsigned expan [4];   /* receives output of E transform */
  1163.   long sbout, scopy;
  1164.   long oarr [2];
  1165.  
  1166.   doip (inar, outar);
  1167.  
  1168.   for (round = 0; round < 16; round++)
  1169.   {
  1170.     sbout = 0L;
  1171.  
  1172.     eexpand (outar [1], expan);
  1173.  
  1174.     for (i = 0; i < 4; i++)
  1175.     { 
  1176.       expan [i] ^= ks [round] [i];
  1177.  
  1178.       for (j = 0; j < 2; j++)
  1179.       {
  1180.         sbout |= snop [(i*2)+j] 
  1181.          [0X3F & (j ? (expan [i] >> 2) : (expan [i] >> 10))];
  1182.       }
  1183.     }
  1184.  
  1185.     scopy = outar [0];
  1186.     outar [0] = outar [1];
  1187.     outar [1] = scopy ^ sbout;
  1188.   }
  1189.  
  1190.   /* a final swap */
  1191.   scopy = outar [0];
  1192.   outar [0] = outar [1];
  1193.   outar [1] = scopy;
  1194.  
  1195.   doipi (outar, oarr);  /* perform ip-inverse into temp copy */
  1196.   outar [0] = oarr [0];
  1197.   outar [1] = oarr [1];
  1198. }
  1199.  
  1200. /* des_decrypt -- decrypt a block under key sched in ks */
  1201. des_decrypt (inar, outar)   
  1202. long    inar [2];
  1203. long    outar [2];
  1204. {
  1205.   extern unsigned ks [16] [4];
  1206.   extern long snop [8] [64];
  1207.  
  1208.   int round, i, j;
  1209.   unsigned expan [4];   /* receives output of E transform */
  1210.   long sbout, scopy;
  1211.   long oarr [2];
  1212.  
  1213.   doip (inar, outar);
  1214.  
  1215.   for (round = 15; round >= 0; round--)
  1216.   /* to do a DES decrypt, use key schedule in reverse order */
  1217.   {
  1218.     sbout = 0L;
  1219.  
  1220.     eexpand (outar [1], expan);
  1221.  
  1222.     for (i = 0; i < 4; i++)
  1223.     { 
  1224.       expan [i] ^= ks [round] [i];
  1225.  
  1226.       for (j = 0; j < 2; j++)
  1227.       {
  1228.         sbout |= snop [(i*2)+j] 
  1229.          [0X3F & (j ? (expan [i] >> 2) : (expan [i] >> 10))];
  1230.       }
  1231.     }
  1232.  
  1233.     scopy = outar [0];
  1234.     outar [0] = outar [1];
  1235.     outar [1] = scopy ^ sbout;
  1236.   }
  1237.  
  1238.   /* a final swap */
  1239.   scopy = outar [0];
  1240.   outar [0] = outar [1];
  1241.   outar [1] = scopy;
  1242.  
  1243.   doipi (outar, oarr);  /* perform ip-inverse into temp copy */
  1244.   outar [0] = oarr [0];
  1245.   outar [1] = oarr [1];
  1246. }
  1247.  
  1248. main ()
  1249. {
  1250.   long plain [2], crypt [2], cprbuf [2];
  1251.  
  1252.   /* begin by reading tables and key schedule from files */
  1253.   printf ("Reading filed tables and key schedule...\n");
  1254.   if (1 != rdfiles ())
  1255.   {
  1256.     printf ("dodes -- couldn't get tables or key schedule\n");
  1257.     exit (1);
  1258.   }
  1259.  
  1260.   printf ("Enter input to encrypt as two hex longs: ");
  1261.   scanf ("%lx %lx", &plain [0], &plain [1]);
  1262.   des_encrypt (plain, crypt);
  1263.   printf ("Encrypted result is: %lx %lx\n", crypt [0], crypt [1]);  
  1264.   des_decrypt (crypt, cprbuf);
  1265.   printf ("Decrypting that result: %lx %lx\n", cprbuf [0], cprbuf [1]);
  1266. }
  1267.  
  1268. #include <stdio.h>
  1269.  
  1270. /* tables to define S boxes and P, per NBS */
  1271.  
  1272. static int s_table [8] [4] [16] =
  1273.     { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
  1274.       0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
  1275.       4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
  1276.       15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
  1277.  
  1278.       15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
  1279.       3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
  1280.       0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
  1281.       13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
  1282.  
  1283.       10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
  1284.       13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
  1285.       13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
  1286.       1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
  1287.  
  1288.       7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
  1289.       13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
  1290.       10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
  1291.       3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
  1292.  
  1293.       2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
  1294.       14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
  1295.       4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
  1296.       11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
  1297.  
  1298.       12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
  1299.       10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
  1300.       9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
  1301.       4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
  1302.  
  1303.       4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
  1304.       13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
  1305.       1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
  1306.       6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
  1307.  
  1308.       13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
  1309.       1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
  1310.       7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
  1311.       2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 };
  1312.  
  1313. static int ptab [32] =
  1314.     { 16, 7, 20, 21,
  1315.       29, 12, 28, 17,
  1316.       1, 15, 23, 26,
  1317.       5, 18, 31, 10,
  1318.       2, 8, 24, 14,
  1319.       32, 27, 3, 9,
  1320.       19, 13, 30, 6,
  1321.       22, 11, 4, 25 };
  1322.  
  1323. /* --- following is code to compute and store optimized tables --- */
  1324. /*
  1325.  
  1326. The ip, ipi, and ipis tables, their use and generation... 
  1327.  
  1328. The IP table is used to perform the IP operations of DES
  1329. efficiently, on a byte-by-byte basis.  There are 256 entries,
  1330. each of which is 64 bits wide.  Each 64 bit entry is composed of
  1331. two longs, and the [0]'th long contains the high order bits.) To
  1332. do the IP transformation, one starts by extracting the rightmost
  1333. byte from the block to be encrypted, and looking up the
  1334. corresponding table entry.  Proceed by shifting the accumulated
  1335. partial IP left one place and inclusive-OR'ing the table value
  1336. for each more significant byte. Continue until all bytes
  1337. have been processed. 
  1338.  
  1339. Regrettably, the structure of the IP-inverse operation is not
  1340. such as to allow table lookup based on bytes selected in
  1341. left-to-right (or right-to-left) order. To compensate for this
  1342. fact, the ipis table is supplied. As one advances through the
  1343. entries in ipis, one finds indexes which select the input byte
  1344. (from 1-8, going left to right) whose value should be used to
  1345. select the next entry in ipi. If this reordering is followed, the
  1346. entries extracted from ipi can be inclusive-OR'd and left shifted
  1347. (in the same manner described for ip), to perform the ip-inverse
  1348. transformation. 
  1349.  
  1350. */
  1351.  
  1352. static long ip [2] [256];     
  1353. static long ipi [2] [256];
  1354. static int ipis [8] = {5, 1, 6, 2, 7, 3, 8, 4};
  1355.  
  1356. /* setipent -- given a byte value, compute the corresponding
  1357.    entry and store it in the ip table. Computation based on
  1358.    embedded knowledge of DES algorithm structure. */
  1359.  
  1360. setipent (val)  
  1361. int     val;
  1362. {
  1363.   extern long ip [2] [256];
  1364.  
  1365.   ip [0] [val] = ip [1] [val] = 0L;
  1366.  
  1367.   if (val & 0X40) ip [0] [val] |= 0X1000000L;
  1368.   if (val & 0X10) ip [0] [val] |= 0X10000L;
  1369.   if (val & 0X4) ip [0] [val] |= 0X100L;
  1370.   if (val & 0X1) ip [0] [val] |= 0X1L;
  1371.   if (val & 0X80) ip [1] [val] |= 0X1000000L;
  1372.   if (val & 0X20) ip [1] [val] |= 0X10000L;
  1373.   if (val & 0X8) ip [1] [val] |= 0X100L;
  1374.   if (val & 0X2) ip [1] [val] |= 0X1L;
  1375. }
  1376.  
  1377. /* setipient -- given a byte value, compute the corresponding
  1378.    entry and store it in the ipi table. Computation based on
  1379.    embedded knowledge of DES algorithm structure. */
  1380.  
  1381. setipient (val)
  1382. int     val;
  1383. {
  1384.   extern long ipi [2] [256];
  1385.  
  1386.   ipi [0] [val] = ipi [1] [val] = 0L;
  1387.  
  1388.   if (val & 0X1) ipi [0] [val] |= 0X1000000L;
  1389.   if (val & 0X2) ipi [0] [val] |= 0X10000L;
  1390.   if (val & 0X4) ipi [0] [val] |= 0X100L;
  1391.   if (val & 0X8) ipi [0] [val] |= 0X1L;
  1392.   if (val & 0X10) ipi [1] [val] |= 0X1000000L;
  1393.   if (val & 0X20) ipi [1] [val] |= 0X10000L;
  1394.   if (val & 0X40) ipi [1] [val] |= 0X100L;
  1395.   if (val & 0X80) ipi [1] [val] |= 0X1L;
  1396. }
  1397.  
  1398. /* setip -- initialize ip and ipi tables */
  1399. setip ()        
  1400. {
  1401.   int i;
  1402.  
  1403.   for (i = 0; i < 256; i++) 
  1404.   {
  1405.     setipent (i);
  1406.     setipient (i);
  1407.   }
  1408. }
  1409.  
  1410.  
  1411. /* 
  1412.  
  1413. the snop table... its generation and use
  1414.  
  1415. Structure snop is a two-dimensional array.  The high-order
  1416. dimension corresponds to 1 of 8 input bytes, each in the format
  1417. produced by skedkeys and the E implementation (each byte has 6
  1418. significant bits, left-justified in an 8-bit byte, and the input
  1419. stream of bytes appears in 4 words as (1 3) (5 7) (2 4) (6 8).
  1420. As the dimension varies from 0->7, bytes are selected from this
  1421. ordering from left to right.
  1422.  
  1423. Using a series of 8 table lookups in snop (one for each byte),
  1424. and IOR'ing the corresponding 32-bit entries, the caller can
  1425. assemble the composition of s-box lookup and P permutation as
  1426. specified in DES.  In a table entry corresponding to a particular
  1427. byte, only those bits are set which correspond to those selected
  1428. by P for the particular s-box.
  1429.  
  1430. The current format for snop has 64, not 256 entries per byte
  1431. position.  Therefore, it is necessary to divide a byte's value by
  1432. 4 before using it as a table index.
  1433.  
  1434. setsnop () computes the entries in snop, based on the NBS tables.
  1435.  
  1436. */
  1437. static long snop [8] [64];
  1438.  
  1439.  
  1440. setsnop ()
  1441. {
  1442.   extern long snop [8] [64];
  1443.  
  1444.   static int map_to_e [8] = {0, 2, 4, 6, 1, 3, 5, 7};
  1445.   /* table used so that bytes ordered as produced by the
  1446.    E algorithm implementation can be looked up left-to-right */
  1447.  
  1448.   int   i, j, ns, ni;
  1449.   int   srow, scol;
  1450.  
  1451.   for (i = 0; i < 8; i++)
  1452.   {
  1453.     for (j = 0; j < 64; j++) snop [i] [j] = 0L;
  1454.   }
  1455.  
  1456.   for (ns = 0; ns < 8; ns++)    /* do for each of 8 S-boxes */
  1457.   {
  1458.     for (ni = 0; ni < 64; ni++) /* do each entry in each box */
  1459.     {
  1460.       srow = ((ni & 32) >> 4) | (ni & 01);      /* lsb and msb of 6 bits */
  1461.       scol = (ni >> 1) & 0XF;
  1462.  
  1463.       /* now, do successive left shifts on a snop entry,
  1464.          IOR'ing in bits iff P selects a position from the S-box */
  1465.  
  1466.       for (i = 0; i < 32; i++)  /* over each bit in the entry */
  1467.       {
  1468.     if (map_to_e[ns] != ((ptab [i] - 1) / 4))
  1469.     {
  1470.       /* this bit not from this S-box: leave alone */
  1471.       if (i != 31) snop [ns] [ni] <<= 1;
  1472.       continue;
  1473.     }
  1474.     else
  1475.     {
  1476.       snop [ns] [ni] |=
  1477.        (01 & (s_table [map_to_e[ns]] [srow] [scol] >> 
  1478.             (3 - ((ptab [i] - 1) % 4))));
  1479.       if (i != 31) snop [ns] [ni] <<= 1;
  1480.     }
  1481.       }
  1482.     }
  1483.   }
  1484.  
  1485. /*
  1486.  for (i = 0; i < 8; i++)
  1487.  {
  1488.    for (j = 0; j < 64; j++)
  1489.     printf ("snop [%d] [%d] = %lx\n", i, j, snop [i] [j]);
  1490.  }
  1491. */
  1492.  
  1493. }
  1494.  
  1495. /* main for tblbuild: compute and output ip, ipi, ipis, snop */
  1496. main ()
  1497. {
  1498.   extern long ip [2] [256];     
  1499.   extern long ipi [2] [256];
  1500.   extern int ipis [8];
  1501.   extern long snop [8] [64];
  1502.   
  1503.   int i, j;
  1504.   FILE *fp, *fopen ();
  1505.  
  1506.   /* compute the static tables */
  1507.   printf ("Computing transformation tables...\n");
  1508.   setip ();
  1509.   setsnop ();
  1510.  
  1511.   if (NULL == (fp = fopen ("ip", "w")))
  1512.   {
  1513.     printf ("tblbuild -- can't open output file 'ip'\n");
  1514.     exit (1);
  1515.   }
  1516.   for (i = 0; i < 2; i++)
  1517.     for (j = 0; j < 256; j++) fprintf (fp, "%lx\n", ip [i] [j]);
  1518.   fclose (fp);
  1519.  
  1520.   if (NULL == (fp = fopen ("ipi", "w")))
  1521.   {
  1522.     printf ("tblbuild -- can't open output file 'ipi'\n");
  1523.     exit (1);
  1524.   }
  1525.   for (i = 0; i < 2; i++)
  1526.     for (j = 0; j < 256; j++) fprintf (fp, "%lx\n", ipi [i] [j]);
  1527.   fclose (fp);
  1528.  
  1529.   if (NULL == (fp = fopen ("ipis", "w")))
  1530.   {
  1531.     printf ("tblbuild -- can't open output file 'ipis'\n");
  1532.     exit (1);
  1533.   }
  1534.   for (i = 0; i < 8; i++) fprintf (fp, "%x\n", ipis [i]);
  1535.   fclose (fp);
  1536.  
  1537.   if (NULL == (fp = fopen ("snop", "w")))
  1538.   {
  1539.     printf ("tblbuild -- can't open output file 'snop'\n");
  1540.     exit (1);
  1541.   }
  1542.   for (i = 0; i < 8; i++)
  1543.     for (j = 0; j < 64; j++) fprintf (fp, "%lx\n", snop [i] [j]);
  1544.   fclose (fp);
  1545.  
  1546.   printf ("tblbuild -- table files output\n");
  1547. }
  1548.  
  1549. /* demodes.c: jl 30 April 1986: demonstrate DES in various modes */
  1550.  
  1551. /* this uses a version of DES that is driven directly            */
  1552. /* from the NBS tables (including E) and hence is rather slow    */
  1553. /* (100ms to encrypt a block on a C/70).                         */
  1554. /* it is fairly compact.                                         */
  1555.  
  1556. /* key schedule code (from dumbksb.c) does not use the pc2 optimization */
  1557. /* and outputs a key schedule as an array of longs               */
  1558. /* where each long contains a 24-bit right-justified             */
  1559. /* quantity, compatible with unoptimized e                       */
  1560.  
  1561. #include        <style.h>
  1562. #include        <stdio.h>
  1563. #include        <ctype.h>
  1564.  
  1565. /* --- some bit manipulation primitives --- */
  1566.  
  1567. /* g_bit -- extract bit bnum from a byte. 
  1568.    As per NBS, MSB is bit 1, LSB bit 8 */
  1569. int g_bit (bnum, byte)
  1570. int             bnum;
  1571. unsigned        byte;
  1572. {
  1573.   byte &= 0XFF;
  1574.   return (01 & (byte >> (8 - bnum)) );
  1575. }
  1576.  
  1577. int     gb_f28 (bnum, lval)     
  1578. /* get the bnum bit from 28-bit lval */
  1579. int     bnum;
  1580. long    lval;
  1581. {
  1582.   return (01 & (lval >> (28 - bnum)) );
  1583. }  
  1584.  
  1585.  
  1586. /* --- following code and data does key schedule generation --- */
  1587. #define NINPC1  28
  1588. #define NINPC2  48
  1589. #define PC2FRR  24      /* number of output bits from C or D */
  1590. #define SUCCESS 0       /* return values from ksmake */
  1591. #define FAILURE 1
  1592.  
  1593. int ksmake (inkey, ks)       /* Make a key schedule from key bytes in inkey */
  1594.                  /* result is SUCCESS if OK, FAILURE otherwise */
  1595. unsigned      inkey [8];
  1596. long          ks [16] [2];
  1597. {
  1598.   static int pc1c [] =
  1599.     { 57, 49, 41, 33, 25, 17, 9,
  1600.       1, 58, 50, 42, 34, 26, 18,
  1601.       10, 2, 59, 51, 43, 35, 27,
  1602.       19, 11, 3, 60, 52, 44, 36 };
  1603.  
  1604.   static int pc1d [] =
  1605.     { 63, 55, 47, 39, 31, 23, 15,
  1606.       7, 62, 54, 46, 38, 30, 22,
  1607.       14, 6, 61, 53, 45, 37, 29,
  1608.       21, 13, 5, 28, 20, 12, 4 };
  1609.  
  1610.   static int shiftsked []=
  1611.      { 1, 1, 2, 2, 2, 2, 2, 2,
  1612.       1, 2, 2, 2, 2, 2, 2, 1 };
  1613.  
  1614.   static int pc2 [] =
  1615.     { 14, 17, 11, 24, 1, 5,
  1616.       3, 28, 15, 6, 21, 10,
  1617.       23, 19, 12, 4, 26, 8,
  1618.       16, 7, 27, 20, 13, 2,
  1619.       41, 52, 31, 37, 47, 55,
  1620.       30, 40, 51, 45, 33, 48,
  1621.       44, 49, 39, 56, 34, 53,
  1622.       46, 42, 50, 36, 29, 32 };
  1623.  
  1624.   int   i, j, parac, round, nshifts;
  1625.   long  pcc, pcd;
  1626.   unsigned incopy;
  1627.  
  1628.   /* first check parity */
  1629.   for (i = 0; i < 8; i++)       /* do each byte */
  1630.   {
  1631.     parac = 0;
  1632.     incopy = inkey [i];
  1633.  
  1634.     for (j = 0; j < 8; j++)     /* 8 bits in a DES byte */
  1635.     {
  1636.       if (incopy & 01) parac++;
  1637.       incopy >>= 1;
  1638.     }
  1639.     if (! (parac & 01)) return (FAILURE); /* no odd parity on this byte */
  1640.   }
  1641.  
  1642.   /* now do pc1 permutation */
  1643.   pcc = pcd = 0L;
  1644.   for (i = 0; i < NINPC1; i++)   /* filling all appropriate bits */
  1645.   {
  1646.     pcc |= (01 & g_bit (pc1c [i] % 8, (unsigned) (inkey [pc1c [i] / 8])));
  1647.     pcd |= (01 & g_bit (pc1d [i] % 8, (unsigned) (inkey [pc1d [i] / 8])));
  1648.     if (i != (NINPC1 - 1))       /* avoid superfluous final shift */
  1649.     {
  1650.       pcc <<= 1;
  1651.       pcd <<= 1;
  1652.     }
  1653.   }
  1654.  
  1655.   for (round = 0; round < 16; round++)
  1656.   {
  1657.     for (nshifts = 0; nshifts < shiftsked [round]; nshifts++)
  1658.     {
  1659.       /* do appropriate number of 28-bit left rotates on pcc, pcd */
  1660.       pcc <<= 1;
  1661.       if (0X10000000L & pcc) pcc++;
  1662.       pcc &= 0XFFFFFFFL;
  1663.       pcd <<= 1;
  1664.       if (0X10000000L & pcd) pcd++;
  1665.       pcd &= 0XFFFFFFFL;
  1666.     }
  1667.  
  1668.     /* Now, pcc and pcd have the values on which we can apply
  1669.        pc2 and select the key bits, storing them in ks[0] and
  1670.        ks[1]. The high order [ks[0]] bits all come from
  1671.        pcc, and the low order from pcd. */
  1672.  
  1673.     ks [round] [0] = ks [round] [1] = 0;
  1674.     for (i = 0; i < PC2FRR; i++)
  1675.     {
  1676.       ks [round] [0] |= gb_f28 (pc2 [i], pcc);
  1677.       if (i != (PC2FRR - 1)) ks [round] [0] <<= 1;
  1678.     }
  1679.     for (i = PC2FRR; i < NINPC2; i++)
  1680.     {
  1681.       ks [round] [1] |= gb_f28 (pc2 [i] - NINPC1, pcd);
  1682.       if (i != (NINPC2 - 1)) ks [round] [1] <<= 1;
  1683.     }
  1684.   }
  1685.   return (SUCCESS);
  1686. }
  1687.  
  1688. #define IP      1       /* flag to select IP */
  1689. #define IPI     IP+1    /* flag to select IPI */
  1690. #define ENCRYPT IPI+1   /* flag to select encryption */
  1691. #define DECRYPT ENCRYPT+1       /* flag to select decryption */
  1692.  
  1693. /* dop -- permute 64 bits via choice of IP or IPI */
  1694. dop (inar, outar, flag)
  1695. long    inar [2];
  1696. long    outar [2];
  1697. int     flag;
  1698. {
  1699.   static int ip [64] =
  1700.     { 58, 50, 42, 34, 26, 18, 10, 2,
  1701.       60, 52, 44, 36, 28, 20, 12, 4,
  1702.       62, 54, 46, 38, 30, 22, 14, 6,
  1703.       64, 56, 48, 40, 32, 24, 16, 8,
  1704.       57, 49, 41, 33, 25, 17, 9, 1,
  1705.       59, 51, 43, 35, 27, 19, 11, 3,
  1706.       61, 53, 45, 37, 29, 21, 13, 5,
  1707.       63, 55, 47, 39, 31, 23, 15, 7};
  1708.  
  1709.   static int ipi [64] =
  1710.     { 40, 8, 48, 16, 56, 24, 64, 32, 
  1711.       39, 7, 47, 15, 55, 23, 63, 31,
  1712.       38, 6, 46, 14, 54, 22, 62, 30,
  1713.       37, 5, 45, 13, 53, 21, 61, 29,
  1714.       36, 4, 44, 12, 52, 20, 60, 28,
  1715.       35, 3, 43, 11, 51, 19, 59, 27,
  1716.       34, 2, 42, 10, 50, 18, 58, 26,
  1717.       33, 1, 41, 9, 49, 17, 57, 25};
  1718.  
  1719.   int i;
  1720.  
  1721.   outar [0] = outar [1] = 0L;
  1722.   for (i = 1; i < 33; i++)
  1723.   {   
  1724.     outar [0] |= 01 & ((((flag == IP) ? ip[i-1] : ipi[i-1]) < 33) ? 
  1725.      (inar [0] >> (32 - ((flag == IP) ? ip[i-1] : ipi[i-1]))) : 
  1726.      (inar [1] >> (64 - ((flag == IP) ? ip[i-1] : ipi[i-1]))) );
  1727.     if (i != 32) outar [0] <<= 1;
  1728.   }
  1729.   for (i = 33; i < 65; i++)
  1730.   {   
  1731.     outar [1] |= 01 & ((((flag == IP) ? ip[i-1] : ipi[i-1]) < 33) ? 
  1732.      (inar [0] >> (32 - ((flag == IP) ? ip[i-1] : ipi[i-1]))) : 
  1733.      (inar [1] >> (64 - ((flag == IP) ? ip[i-1] : ipi[i-1]))) );
  1734.     if (i != 64) outar [1] <<= 1;
  1735.   }
  1736. }
  1737.  
  1738. /* dodes -- encrypt or decrypt a block under key sched in ks */
  1739. dodes (inar, outar, flag, ks)
  1740. long    inar [2];
  1741. long    outar [2];
  1742. int     flag;
  1743. long    ks [16] [2];
  1744. {
  1745. /* tables to define S boxes and P, per NBS */
  1746.  
  1747.   static int s_table [8] [4] [16] =
  1748.     { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
  1749.       0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
  1750.       4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
  1751.       15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
  1752.  
  1753.       15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
  1754.       3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
  1755.       0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
  1756.       13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
  1757.  
  1758.       10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
  1759.       13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
  1760.       13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
  1761.       1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
  1762.  
  1763.       7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
  1764.       13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
  1765.       10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
  1766.       3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
  1767.  
  1768.       2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
  1769.       14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
  1770.       4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
  1771.       11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
  1772.  
  1773.       12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
  1774.       10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
  1775.       9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
  1776.       4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
  1777.  
  1778.       4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
  1779.       13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
  1780.       1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
  1781.       6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
  1782.  
  1783.       13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
  1784.       1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
  1785.       7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
  1786.       2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 };
  1787.  
  1788.   static int ptab [32] =
  1789.     { 16, 7, 20, 21,
  1790.       29, 12, 28, 17,
  1791.       1, 15, 23, 26,
  1792.       5, 18, 31, 10,
  1793.       2, 8, 24, 14,
  1794.       32, 27, 3, 9,
  1795.       19, 13, 30, 6,
  1796.       22, 11, 4, 25 };
  1797.  
  1798.   static int etab [48] = 
  1799.     { 32, 1, 2, 3, 4, 5,
  1800.       4, 5, 6, 7, 8, 9,
  1801.       8, 9, 10, 11, 12, 13,
  1802.       12, 13, 14, 15, 16, 17,
  1803.       16, 17, 18, 19, 20, 21,
  1804.       20, 21, 22, 23, 24, 25,
  1805.       24, 25, 26, 27, 28, 29,
  1806.       28, 29, 30, 31, 32, 1};
  1807.  
  1808.   register int round, sb, sbidx, i, j;
  1809.   long expan [2];   /* receives output of E transform */
  1810.   long sbout, scopy;
  1811.   long oarr [2];
  1812.  
  1813.   dop (inar, outar, IP);
  1814.  
  1815.   for (round = 0; round < 16; round++)
  1816.   {
  1817.   /* first perform des e transformation of 32->48 bits.
  1818.    accepts an input long, returns result into an array of two longs
  1819.    with 24 low-order bits in each element */
  1820.     expan [0] = expan [1] = 0L;
  1821.     for (i = 1; i < 25; i++)
  1822.     {
  1823.       expan [0] |= 01 & (outar [1] >> (32 - etab[i-1]));    
  1824.       if (i != 24) expan [0] <<= 1;
  1825.     }
  1826.     for (i = 25; i < 49; i++)
  1827.     {
  1828.       expan [1] |= 01 & (outar [1] >> (32 - etab[i-1]));
  1829.       if (i != 48) expan [1] <<= 1;
  1830.     }
  1831.   /* xor expanded quantity with key schedule */
  1832.     expan [0] ^= ks [(flag == ENCRYPT) ? round : 15 - round] [0];
  1833.     expan [1] ^= ks [(flag == ENCRYPT) ? round : 15 - round] [1];
  1834.     scopy = 0L;
  1835.     for (sb = 0; sb < 8; sb++)
  1836.     {  /* look up bits in s-boxes, filling a 32 bit word */
  1837.       sbidx = 0X3F & ((sb < 4) ? 
  1838.       (expan [0] >> (18 - (6 * sb))) : (expan [1] >> (18 - (6 * (sb-4)))) );
  1839.       /* select bits per nbs spec */
  1840.       i = sbidx; i &= 0X20; i >>= 4; i |= 01 & sbidx;      
  1841.       j = sbidx; j &= 0X1E; j >>= 1;
  1842.       scopy |= s_table [sb] [i] [j];
  1843.       if (sb != 7) scopy <<= 4;
  1844.     }
  1845.     /* now, perform p permutation into 'sbout' */
  1846.     sbout = 0L;
  1847.     for (i = 1; i < 33; i++)
  1848.     {
  1849.       sbout |= 01 & (scopy >> (32 - ptab [i-1]));
  1850.       if (i != 32) sbout <<= 1;
  1851.     }
  1852.  
  1853.     scopy = outar [0];
  1854.     outar [0] = outar [1];
  1855.     outar [1] = scopy ^ sbout;
  1856.   }
  1857.  
  1858.   /* a final swap into temp copy - let dop move into true output array */
  1859.   scopy = outar [0];
  1860.   oarr [0] = outar [1];
  1861.   oarr [1] = scopy;
  1862.   dop (oarr, outar, IPI);
  1863. }
  1864.  
  1865. /* support routines for demodes */
  1866.  
  1867. /* read input bytes from stdin */
  1868. int     g_inbytes (nby, buffer)     /* returns TRUE iff EOF reached */
  1869. int     nby;        /* number of bytes needed at a time */
  1870.             /* if insufficient, will be padded with nulls */
  1871. char    buffer [];
  1872. {
  1873.   int   bufix;
  1874.   int   getcval;
  1875.  
  1876.   /* init all significant bytes to null pad */
  1877.   for (bufix = 0; bufix < nby; bufix++) buffer[bufix] = 0;
  1878.  
  1879.   for (bufix = 0; bufix < nby; bufix++)
  1880.   {
  1881.     getcval = getchar ();
  1882.     buffer [bufix] = (char) getcval;
  1883.     if (getcval == EOF)
  1884.     {
  1885.       buffer[bufix] = 0;        /* replace with pad */
  1886.       return (TRUE);            /* indicating that EOF detected */
  1887.     }
  1888.   }
  1889.   return (FALSE);       /* indicating no EOF detected */
  1890. }
  1891.  
  1892. /* represent a series of bytes (conditionally) in two buffers, as
  1893.    printable representation and hex representation */
  1894. di_bytes (nby, inbuf, pr_buf, hx_buf)
  1895. int     nby;
  1896. char    inbuf [];
  1897. char    pr_buf [];      /* NULL if not desired */
  1898. char    hx_buf [];      /* NULL if not desired */
  1899. {
  1900.   int i;
  1901.  
  1902.   for (i = 0; i < nby; i++)
  1903.   {
  1904.     if (pr_buf != NULL)
  1905.     {
  1906.       /* Try to show as a printable character, either directly or */
  1907.       /* by masking off the MSB (if the latter, prefix with '#') */
  1908.       if (inbuf [i] > 0x7f)
  1909.       {
  1910.     if (isprint (inbuf [i] & 0x7f))
  1911.       sprintf (pr_buf, "#%c", inbuf [i] & 0x7f);
  1912.     else sprintf (pr_buf, "  ");
  1913.       }
  1914.       else
  1915.       {
  1916.     if (isprint (inbuf [i]))
  1917.       sprintf (pr_buf, " %c", inbuf [i]);
  1918.     else sprintf (pr_buf, "  ");
  1919.       }
  1920.       pr_buf += 2;
  1921.     }
  1922.     if (hx_buf != NULL)
  1923.     {
  1924.       sprintf (hx_buf, "%1x%1x", 0xf & (inbuf[i]>>4),0xf & inbuf [i]);
  1925.       hx_buf += 2;
  1926.     }
  1927.   }
  1928.   if (pr_buf != NULL) sprintf (pr_buf, "|");
  1929.   if (hx_buf != NULL) sprintf (hx_buf, "|");
  1930. }
  1931.  
  1932. packbtol (as_ba, as_l)   /* pack 4 bytes into a long */
  1933. char    as_ba [];
  1934. long    *as_l;
  1935. {
  1936.   long lt;
  1937.  
  1938.   lt = as_ba [0] & 0xff;
  1939.   lt <<= 8;
  1940.   lt |= as_ba [1] & 0xff;
  1941.   lt <<= 8;
  1942.   lt |= as_ba [2] & 0xff;
  1943.   lt <<= 8;
  1944.   lt |= as_ba [3] & 0xff;
  1945.  
  1946.   *as_l = lt;
  1947. }
  1948.  
  1949. sprdltob (as_l, as_ba)  /* spread a long into 4 bytes */
  1950. long    as_l;
  1951. char    as_ba [];
  1952. {
  1953.   as_ba [0] = (char) ((as_l >> 24) & 0xff);
  1954.   as_ba [1] = (char) ((as_l >> 16) & 0xff);
  1955.   as_ba [2] = (char) ((as_l >> 8) & 0xff);
  1956.   as_ba [3] = (char) (as_l & 0xff);
  1957. }
  1958.  
  1959. lsh64 (lar, count)      /* left shift a 64-bit quantity maintained */
  1960. long    lar[];          /* in a 2-element long array. Assumes that */
  1961. int     count;          /* a long has at least 32 bits */
  1962. {
  1963.   int   i; 
  1964.   long  t;
  1965.  
  1966.   for (i = 0; i < count; i++)
  1967.   {
  1968.     t = (lar [1] >> 31) & 0x1l;
  1969.     lar [1] <<= 1;
  1970.     lar [0] <<= 1;
  1971.     lar [0] |= t;
  1972.   }  
  1973.   lar [0] &= 0xffffffffl;
  1974.   lar [1] &= 0xffffffffl;
  1975. }
  1976.  
  1977. rsh64 (lar, count)      /* right shift a 64-bit quantity maintained */
  1978. long    lar[];          /* in a 2-element long array. Assumes that */
  1979. int     count;          /* a long has at least 32 bits */
  1980. {
  1981.   int   i; 
  1982.   long  t;
  1983.  
  1984.   for (i = 0; i < count; i++)
  1985.   {
  1986.     t = lar [0] & 0x1l;
  1987.     lar [1] >>= 1;
  1988.     lar [0] >>= 1;
  1989.     lar [1] |= (t << 31);
  1990.   }  
  1991. }
  1992.  
  1993. rplr64 (base, modr, nbits)      /* replace rightmost nbits of base */
  1994. long    base[];                 /* (64-bit qty in 2-elmt long array) */
  1995. long    modr[];                 /* with corresponding bits from modr */
  1996. int     nbits;
  1997. {       /* Assumes longs are 32 bits or more */
  1998.   long  mask;
  1999.   long  lmod;   /* local copy of modr word */
  2000.  
  2001.   mask = (nbits >= 32) ? 0xffffffffl : ((0x1l << nbits) - 1);
  2002. /*  mask = (0x1l << ((nbits > 32) ? 32 : nbits)) - 1; */
  2003.   base [1] &= ~mask;    /* wipe out existing low bits */
  2004.   lmod = modr [1] & mask;
  2005.   base [1] |= lmod;
  2006.  
  2007.   nbits -= 32;
  2008.   if (nbits <= 0) return;
  2009.   
  2010.   mask = (0x1l << nbits) - 1;
  2011.   base [0] &= ~mask;
  2012.   lmod = modr [0] & mask;
  2013.   base [0] |= lmod;
  2014. }
  2015.  
  2016. cpy64 (src, dest)       /* copy src 2-elmt long array to dest */
  2017. long    src[];
  2018. long    dest[];
  2019. {
  2020.   dest [0] = src [0];
  2021.   dest [1] = src [1];
  2022. }
  2023.  
  2024. #define ECB     1
  2025. #define CBC     ECB+1
  2026. #define OFB     CBC+1
  2027. #define CFB     OFB+1
  2028.  
  2029. main (argc,argv)
  2030. int     argc;
  2031. char    *argv [];
  2032. {
  2033.   int   argn;
  2034.   int   dmode;
  2035.   int   eofyet = FALSE; /* will set to TRUE when end of input */
  2036.   int   quant = 0;      /* quantum size (in bits) for selected mode */
  2037.   int   flwid;          /* size to display a 64-bit chunk of pt or ct */
  2038.   int   i, j;
  2039.   long  iv [2], keyl [2];
  2040.  
  2041.   unsigned      inkey [8];
  2042.   char  inkeyc [8]; 
  2043.   char  inbbuf [8], otbbuf [8];
  2044.   char  iprline [80], ihxline [80], ohxline [80];
  2045.   long      ks [16] [2];
  2046.  
  2047.   long plain [2], crypt [2], cprbuf [2], cipher [2];
  2048.  
  2049.   /* default key and IV to NBS sample values */
  2050.   keyl [0] = 0x01234567l;
  2051.   keyl [1] = 0x89abcdefl;
  2052.   iv [0] = 0x12345678l;
  2053.   iv [1] = 0x90abcdefl;
  2054.  
  2055.   /* scan the command line */
  2056.   for (argn = 1; argn <= argc; argn++)
  2057.   {
  2058.     if (seq_nocase (argv[argn], "-m")) /* mode specifier */
  2059.     {  /* one string argument expected */
  2060.       argn++;
  2061.       if (seq_nocase (argv[argn], "ecb")) 
  2062.       {
  2063.         dmode = ECB; quant = 64;
  2064.       }
  2065.       else if (seq_nocase (argv[argn], "cbc")) 
  2066.       {
  2067.         dmode = CBC; quant = 64;
  2068.       }
  2069.       else if (seq_nocase (argv[argn], "ofb")) 
  2070.       {
  2071.         dmode = OFB; if (quant == 0) quant = 64; /* may be overridden */
  2072.       }
  2073.       else if (seq_nocase (argv[argn], "cfb")) 
  2074.       {
  2075.         dmode = CFB; if (quant == 0) quant = 64; /* may be overridden */
  2076.       }
  2077.     }
  2078.     else if (seq_nocase (argv[argn], "-k"))    /* key specifier */
  2079.     {  /* two long hex numerics expected */
  2080.       argn++;
  2081.       sscanf (argv[argn], "%lx", &keyl [0]);
  2082.       argn++;
  2083.       sscanf (argv[argn], "%lx", &keyl [1]);
  2084.     }
  2085.     else if (seq_nocase (argv[argn], "-iv"))   /* IV specifier */
  2086.     {  /* two long hex numerics expected */
  2087.       argn++;
  2088.       sscanf (argv[argn], "%lx", &iv [0]);
  2089.       argn++;
  2090.       sscanf (argv[argn], "%lx", &iv [1]);
  2091.     }
  2092.     else if (seq_nocase (argv[argn], "-q"))     /* quantum specifier */
  2093.     { /* one decimal number expected */
  2094.       argn++;
  2095.       sscanf (argv[argn], "%d", &quant);
  2096.     }
  2097.   }
  2098.  
  2099.   if (((dmode == ECB) || (dmode == CBC)) && (quant != 64))
  2100.   {
  2101.     printf ("Can't override quantum of 64 for ECB or CBC modes... aborting\n");
  2102.     exit (1);
  2103.   }
  2104.  
  2105.   /* build key schedule (outside scanner, so default works) */
  2106.   sprdltob (keyl [0], & inkeyc [0]);
  2107.   sprdltob (keyl [1], & inkeyc [4]);
  2108.   for (i = 0; i < 8; i++) inkey [i] = (unsigned) (inkeyc [i] & 0xff);
  2109.   if (ksmake (inkey, ks) != SUCCESS)
  2110.   {
  2111.     printf ("Bad parity on key... aborting...\n");
  2112.     exit (1);
  2113.   }
  2114.  
  2115.   printf ("Mode is ");
  2116.   switch (dmode)
  2117.   {
  2118.     case ECB:
  2119.       printf ("ECB;");
  2120.       break;
  2121.     case CBC:
  2122.       printf ("CBC;");
  2123.       break;
  2124.     case OFB:
  2125.       printf ("OFB;");
  2126.       printf (" Quantum is %d;", quant);
  2127.       break;
  2128.     case CFB:
  2129.       printf ("CFB;");
  2130.       printf (" Quantum is %d;", quant);
  2131.       break;
  2132.     default:
  2133.       printf ("Unknown;");
  2134.       break;
  2135.   }
  2136.   printf (" Key is %lx %lx;", keyl [0], keyl [1]);
  2137.   if (dmode != ECB) printf (" IV is %lx %lx;", iv [0], iv [1]);
  2138.   printf ("\n");
  2139.  
  2140.   flwid = (8 * 2) + 1;      /* 8 bytes, 2 chars/byte, and a delimiter */
  2141.  
  2142.   while (eofyet == FALSE)       /* until EOF detected on input */
  2143.   {
  2144.     if (dmode == ECB)
  2145.     {
  2146.       for (i = 0; i < 4; i++)     /* 4 groups on a printable line */
  2147.       {
  2148.         if (TRUE == g_inbytes (8, inbbuf)) eofyet = TRUE;
  2149.         di_bytes (8, inbbuf, &iprline [flwid*i], &ihxline [flwid*i]);
  2150.         packbtol (&inbbuf[0], &plain[0]);
  2151.         packbtol (&inbbuf[4], &plain[1]);
  2152.         dodes (plain, crypt, ENCRYPT, ks);
  2153.         sprdltob (crypt[0], &otbbuf[0]);
  2154.         sprdltob (crypt[1], &otbbuf[4]);
  2155.         di_bytes (8, otbbuf, NULL, &ohxline [flwid*i]);
  2156.     if (TRUE == eofyet) break;
  2157.       }
  2158.     }
  2159.     else if (dmode == CBC)
  2160.     {
  2161.       for (i = 0; i < 4; i++)     /* 4 groups on a printable line */
  2162.       {
  2163.         if (TRUE == g_inbytes (8, inbbuf)) eofyet = TRUE;
  2164.         di_bytes (8, inbbuf, &iprline [flwid*i], &ihxline [flwid*i]);
  2165.         packbtol (&inbbuf[0], &plain[0]);
  2166.         packbtol (&inbbuf[4], &plain[1]);
  2167.     plain [0] ^= iv [0];    /* XOR IV with input plaintext */
  2168.         plain [1] ^= iv [1];
  2169.         dodes (plain, crypt, ENCRYPT, ks);
  2170.         sprdltob (crypt[0], &otbbuf[0]);
  2171.         sprdltob (crypt[1], &otbbuf[4]);
  2172.         di_bytes (8, otbbuf, NULL, &ohxline [flwid*i]);
  2173.     iv [0] = crypt [0];     /* use ciphertext output as next IV */
  2174.         iv [1] = crypt [1];
  2175.     if (TRUE == eofyet) break;
  2176.       }
  2177.     }
  2178.     else if (dmode == CFB)
  2179.     {
  2180.       for (i = 0; i < 4; i++)     /* 4 groups on a printable line */
  2181.       /* does file read and display in 64-bit units regardless of quantum */
  2182.       {
  2183.         if (TRUE == g_inbytes (8, inbbuf)) eofyet = TRUE;
  2184.         di_bytes (8, inbbuf, &iprline [flwid*i], &ihxline [flwid*i]);
  2185.         packbtol (&inbbuf[0], &plain[0]);
  2186.         packbtol (&inbbuf[4], &plain[1]);
  2187.     for (j = 0; j < 64; j+=quant)
  2188.     {
  2189.           dodes (iv, crypt, ENCRYPT, ks);
  2190.       rsh64 (crypt, 64-quant);      /* right-align active DES output bits */
  2191.       cpy64 (plain, cprbuf);        /* copy plaintext to scratch */
  2192.       rsh64 (cprbuf, 64-(quant+j)); /* right-align active plaintext bits */
  2193.       /* XOR them into DES output */
  2194.       crypt [0] ^= cprbuf [0];  crypt [1] ^= cprbuf [1];
  2195.       lsh64 (iv, quant);            /* shift existing IV over */
  2196.       rplr64 (iv, crypt, quant);    /* replace LS IV bits with DES output */
  2197.       lsh64 (cipher, quant);        /* make space in cipher out array */
  2198.       rplr64 (cipher, crypt, quant); /* insert new output bits */
  2199.     }
  2200.         sprdltob (cipher[0], &otbbuf[0]);
  2201.         sprdltob (cipher[1], &otbbuf[4]);
  2202.         di_bytes (8, otbbuf, NULL, &ohxline [flwid*i]);
  2203.     if (TRUE == eofyet) break;
  2204.       }
  2205.     }
  2206.     else if (dmode == OFB)
  2207.     {
  2208.       for (i = 0; i < 4; i++)     /* 4 groups on a printable line */
  2209.       {
  2210.         if (TRUE == g_inbytes (8, inbbuf)) eofyet = TRUE;
  2211.         di_bytes (8, inbbuf, &iprline [flwid*i], &ihxline [flwid*i]);
  2212.         packbtol (&inbbuf[0], &plain[0]);
  2213.         packbtol (&inbbuf[4], &plain[1]);
  2214.     for (j = 0; j < 64; j+=quant)
  2215.     {
  2216.           dodes (iv, crypt, ENCRYPT, ks);
  2217.       rsh64 (crypt, 64-quant);      /* right-align active DES output bits */
  2218.       lsh64 (iv, quant);            /* shift existing IV over */
  2219.       rplr64 (iv, crypt, quant);    /* replace LS IV bits with DES output */
  2220.       cpy64 (plain, cprbuf);        /* copy plaintext to scratch */
  2221.       rsh64 (cprbuf, 64-(quant+j)); /* right-align active plaintext bits */
  2222.       /* XOR them into DES output */
  2223.       crypt [0] ^= cprbuf [0];  crypt [1] ^= cprbuf [1];
  2224.       lsh64 (cipher, quant);        /* make space in cipher out array */
  2225.       rplr64 (cipher, crypt, quant); /* insert new output bits */
  2226.     }
  2227.         sprdltob (cipher[0], &otbbuf[0]);
  2228.         sprdltob (cipher[1], &otbbuf[4]);
  2229.     di_bytes (8, otbbuf, NULL, &ohxline [flwid*i]);
  2230.         if (TRUE == eofyet) break;
  2231.       }                      
  2232.     }
  2233.     printf ("%s\n%s\n%s\n", iprline, ihxline, ohxline);
  2234.   }
  2235.   printf ("\n");
  2236. }
  2237.  
  2238. /* ------------------------------------------------------ */
  2239. /* This DES software was developed by Steve Kent and John Linn */
  2240. /* at BBN Communications Corporation, Cambridge, MA */
  2241. /* Do not redistribute this software, or integrate with other */
  2242. /* software, without preserving this notice */
  2243. /* ------------------------------------------------------ */
  2244.  
  2245. /* fastdemo.c: jl 5 May 1986: demonstrate DES in various modes, using */
  2246. /* optimized DES version */
  2247. /* changes 2 June 1986: */
  2248. /* use Dan Hoey's IP, IP-1 optimization */
  2249.  
  2250. /* define TIMEONLY to time DES cycles rather than run ordinary demo */
  2251. /* timing data on C/70, (compiled -O) with 500 iterations */
  2252. /* (each iteration is an encrypt+decrypt) */
  2253. /* without HOEYOPT: typical DES op is about 7.825 msec (470 ticks/1000 opns) */
  2254. /* with HOEYOPT: typical DES op is about 7.425 msec (445 ticks/1000 opns) */
  2255. /* this compares with VAX timing of a slightly different version, */
  2256. /* (pre-HOEYOPT) of 2.6 ms/cycle */
  2257.  
  2258. /* Additional timing data, from David Balenson at NBS, March 1988 */
  2259. /* I initially tried it on our VAX 11/750 and SUN 3/160 (both */
  2260. /* running UNIX BSD 4.2) and acheived measurements of 15.3Kbps on the */
  2261. /* VAX and 54.1Kbps(!!!) on the SUN.  It also compiled and ran successfully */
  2262. /* under PC-DOS using the Computer Innovations C86 C compiler.  I added */
  2263. /* DOS-based timing routines in place of your UNIX routines and got times */
  2264. /* of 8.4Kbps on an 8MHz AT and 10.2Kbps on a PS/2-50. */
  2265.  
  2266. #include        <stdio.h>
  2267. #include        <ctype.h>
  2268.  
  2269. #define FALSE   0
  2270. #define TRUE    1
  2271.  
  2272. #define ECB     1
  2273. #define CBC     ECB+1
  2274. #define OFB     CBC+1
  2275. #define CFB     OFB+1
  2276.  
  2277. /* Dan Hoey (hoey@nrl-aic)'s optimization, per 16 May 1986 netmail */
  2278. /* Exchange bits of A selected by mask M with bits of B selected by */
  2279. /* mask (M << S). TMP is a temporary. */
  2280. #define EXSHMSK(A,M,B,S,TMP)    \
  2281.     TMP = ((B >> S) ^ A) & M;   \
  2282.     A ^= TMP;                   \
  2283.     TMP <<= S;                  \
  2284.     B ^= TMP
  2285.  
  2286. /* tables to describe permutations, per NBS FIPS */
  2287.  
  2288. static int pc1c [] =
  2289.     { 57, 49, 41, 33, 25, 17, 9,
  2290.       1, 58, 50, 42, 34, 26, 18,
  2291.       10, 2, 59, 51, 43, 35, 27,
  2292.       19, 11, 3, 60, 52, 44, 36 };
  2293.  
  2294. static int pc1d [] =
  2295.     { 63, 55, 47, 39, 31, 23, 15,
  2296.       7, 62, 54, 46, 38, 30, 22,
  2297.       14, 6, 61, 53, 45, 37, 29,
  2298.       21, 13, 5, 28, 20, 12, 4 };
  2299.  
  2300. static int shiftsked []=
  2301.     { 1, 1, 2, 2, 2, 2, 2, 2,
  2302.       1, 2, 2, 2, 2, 2, 2, 1 };
  2303.  
  2304. #ifdef  TIMEONLY
  2305. /* facilities for timing */
  2306. struct tbuffer
  2307. {
  2308.   long proc_utime;
  2309.   long proc_stime;
  2310.   long child_utime;
  2311.   long child_stime;
  2312. };
  2313. struct tbuffer t_before;
  2314. struct tbuffer t_after;
  2315. #endif
  2316.  
  2317. long snop [8] [64] = {
  2318. 0X808200L,0X0L,0X8000L,0X808202L,
  2319. 0X808002L,0X8202L,0X2L,0X8000L,
  2320. 0X200L,0X808200L,0X808202L,0X200L,
  2321. 0X800202L,0X808002L,0X800000L,0X2L,
  2322. 0X202L,0X800200L,0X800200L,0X8200L,
  2323. 0X8200L,0X808000L,0X808000L,0X800202L,
  2324. 0X8002L,0X800002L,0X800002L,0X8002L,
  2325. 0X0L,0X202L,0X8202L,0X800000L,
  2326. 0X8000L,0X808202L,0X2L,0X808000L,
  2327. 0X808200L,0X800000L,0X800000L,0X200L,
  2328. 0X808002L,0X8000L,0X8200L,0X800002L,
  2329. 0X200L,0X2L,0X800202L,0X8202L,
  2330. 0X808202L,0X8002L,0X808000L,0X800202L,
  2331. 0X800002L,0X202L,0X8202L,0X808200L,
  2332. 0X202L,0X800200L,0X800200L,0X0L,
  2333. 0X8002L,0X8200L,0X0L,0X808002L,
  2334.  
  2335. 0X104L,0X4010100L,0X0L,0X4010004L,
  2336. 0X4000100L,0X0L,0X10104L,0X4000100L,
  2337. 0X10004L,0X4000004L,0X4000004L,0X10000L,
  2338. 0X4010104L,0X10004L,0X4010000L,0X104L,
  2339. 0X4000000L,0X4L,0X4010100L,0X100L,
  2340. 0X10100L,0X4010000L,0X4010004L,0X10104L,
  2341. 0X4000104L,0X10100L,0X10000L,0X4000104L,
  2342. 0X4L,0X4010104L,0X100L,0X4000000L,
  2343. 0X4010100L,0X4000000L,0X10004L,0X104L,
  2344. 0X10000L,0X4010100L,0X4000100L,0X0L,
  2345. 0X100L,0X10004L,0X4010104L,0X4000100L,
  2346. 0X4000004L,0X100L,0X0L,0X4010004L,
  2347. 0X4000104L,0X10000L,0X4000000L,0X4010104L,
  2348. 0X4L,0X10104L,0X10100L,0X4000004L,
  2349. 0X4010000L,0X4000104L,0X104L,0X4010000L,
  2350. 0X10104L,0X4L,0X4010004L,0X10100L,
  2351.  
  2352. 0X80L,0X1040080L,0X1040000L,0X21000080L,
  2353. 0X40000L,0X80L,0X20000000L,0X1040000L,
  2354. 0X20040080L,0X40000L,0X1000080L,0X20040080L,
  2355. 0X21000080L,0X21040000L,0X40080L,0X20000000L,
  2356. 0X1000000L,0X20040000L,0X20040000L,0X0L,
  2357. 0X20000080L,0X21040080L,0X21040080L,0X1000080L,
  2358. 0X21040000L,0X20000080L,0X0L,0X21000000L,
  2359. 0X1040080L,0X1000000L,0X21000000L,0X40080L,
  2360. 0X40000L,0X21000080L,0X80L,0X1000000L,
  2361. 0X20000000L,0X1040000L,0X21000080L,0X20040080L,
  2362. 0X1000080L,0X20000000L,0X21040000L,0X1040080L,
  2363. 0X20040080L,0X80L,0X1000000L,0X21040000L,
  2364. 0X21040080L,0X40080L,0X21000000L,0X21040080L,
  2365. 0X1040000L,0X0L,0X20040000L,0X21000000L,
  2366. 0X40080L,0X1000080L,0X20000080L,0X40000L,
  2367. 0X0L,0X20040000L,0X1040080L,0X20000080L,
  2368.  
  2369. 0X100000L,0X2100001L,0X2000401L,0X0L,
  2370. 0X400L,0X2000401L,0X100401L,0X2100400L,
  2371. 0X2100401L,0X100000L,0X0L,0X2000001L,
  2372. 0X1L,0X2000000L,0X2100001L,0X401L,
  2373. 0X2000400L,0X100401L,0X100001L,0X2000400L,
  2374. 0X2000001L,0X2100000L,0X2100400L,0X100001L,
  2375. 0X2100000L,0X400L,0X401L,0X2100401L,
  2376. 0X100400L,0X1L,0X2000000L,0X100400L,
  2377. 0X2000000L,0X100400L,0X100000L,0X2000401L,
  2378. 0X2000401L,0X2100001L,0X2100001L,0X1L,
  2379. 0X100001L,0X2000000L,0X2000400L,0X100000L,
  2380. 0X2100400L,0X401L,0X100401L,0X2100400L,
  2381. 0X401L,0X2000001L,0X2100401L,0X2100000L,
  2382. 0X100400L,0X0L,0X1L,0X2100401L,
  2383. 0X0L,0X100401L,0X2100000L,0X400L,
  2384. 0X2000001L,0X2000400L,0X400L,0X100001L,
  2385.  
  2386. 0X40084010L,0X40004000L,0X4000L,0X84010L,
  2387. 0X80000L,0X10L,0X40080010L,0X40004010L,
  2388. 0X40000010L,0X40084010L,0X40084000L,0X40000000L,
  2389. 0X40004000L,0X80000L,0X10L,0X40080010L,
  2390. 0X84000L,0X80010L,0X40004010L,0X0L,
  2391. 0X40000000L,0X4000L,0X84010L,0X40080000L,
  2392. 0X80010L,0X40000010L,0X0L,0X84000L,
  2393. 0X4010L,0X40084000L,0X40080000L,0X4010L,
  2394. 0X0L,0X84010L,0X40080010L,0X80000L,
  2395. 0X40004010L,0X40080000L,0X40084000L,0X4000L,
  2396. 0X40080000L,0X40004000L,0X10L,0X40084010L,
  2397. 0X84010L,0X10L,0X4000L,0X40000000L,
  2398. 0X4010L,0X40084000L,0X80000L,0X40000010L,
  2399. 0X80010L,0X40004010L,0X40000010L,0X80010L,
  2400. 0X84000L,0X0L,0X40004000L,0X4010L,
  2401. 0X40000000L,0X40080010L,0X40084010L,0X84000L,
  2402.  
  2403. 0X80401000L,0X80001040L,0X80001040L,0X40L,
  2404. 0X401040L,0X80400040L,0X80400000L,0X80001000L,
  2405. 0X0L,0X401000L,0X401000L,0X80401040L,
  2406. 0X80000040L,0X0L,0X400040L,0X80400000L,
  2407. 0X80000000L,0X1000L,0X400000L,0X80401000L,
  2408. 0X40L,0X400000L,0X80001000L,0X1040L,
  2409. 0X80400040L,0X80000000L,0X1040L,0X400040L,
  2410. 0X1000L,0X401040L,0X80401040L,0X80000040L,
  2411. 0X400040L,0X80400000L,0X401000L,0X80401040L,
  2412. 0X80000040L,0X0L,0X0L,0X401000L,
  2413. 0X1040L,0X400040L,0X80400040L,0X80000000L,
  2414. 0X80401000L,0X80001040L,0X80001040L,0X40L,
  2415. 0X80401040L,0X80000040L,0X80000000L,0X1000L,
  2416. 0X80400000L,0X80001000L,0X401040L,0X80400040L,
  2417. 0X80001000L,0X1040L,0X400000L,0X80401000L,
  2418. 0X40L,0X400000L,0X1000L,0X401040L,
  2419.  
  2420. 0X10000008L,0X10200000L,0X2000L,0X10202008L,
  2421. 0X10200000L,0X8L,0X10202008L,0X200000L,
  2422. 0X10002000L,0X202008L,0X200000L,0X10000008L,
  2423. 0X200008L,0X10002000L,0X10000000L,0X2008L,
  2424. 0X0L,0X200008L,0X10002008L,0X2000L,
  2425. 0X202000L,0X10002008L,0X8L,0X10200008L,
  2426. 0X10200008L,0X0L,0X202008L,0X10202000L,
  2427. 0X2008L,0X202000L,0X10202000L,0X10000000L,
  2428. 0X10002000L,0X8L,0X10200008L,0X202000L,
  2429. 0X10202008L,0X200000L,0X2008L,0X10000008L,
  2430. 0X200000L,0X10002000L,0X10000000L,0X2008L,
  2431. 0X10000008L,0X10202008L,0X202000L,0X10200000L,
  2432. 0X202008L,0X10202000L,0X0L,0X10200008L,
  2433. 0X8L,0X2000L,0X10200000L,0X202008L,
  2434. 0X2000L,0X200008L,0X10002008L,0X0L,
  2435. 0X10202000L,0X10000000L,0X200008L,0X10002008L,
  2436.  
  2437. 0X8000820L,0X800L,0X20000L,0X8020820L,
  2438. 0X8000000L,0X8000820L,0X20L,0X8000000L,
  2439. 0X20020L,0X8020000L,0X8020820L,0X20800L,
  2440. 0X8020800L,0X20820L,0X800L,0X20L,
  2441. 0X8020000L,0X8000020L,0X8000800L,0X820L,
  2442. 0X20800L,0X20020L,0X8020020L,0X8020800L,
  2443. 0X820L,0X0L,0X0L,0X8020020L,
  2444. 0X8000020L,0X8000800L,0X20820L,0X20000L,
  2445. 0X20820L,0X20000L,0X8020800L,0X800L,
  2446. 0X20L,0X8020020L,0X800L,0X20820L,
  2447. 0X8000800L,0X20L,0X8000020L,0X8020000L,
  2448. 0X8020020L,0X8000000L,0X20000L,0X8000820L,
  2449. 0X0L,0X8020820L,0X20020L,0X8000020L,
  2450. 0X8020000L,0X8000800L,0X8000820L,0X0L,
  2451. 0X8020820L,0X20800L,0X20800L,0X820L,
  2452. 0X820L,0X20020L,0X8000000L,0X8020800L 
  2453. };
  2454.  
  2455. long pc2otab [8] [128] = {
  2456. 0X0L,0X10L,0X4000L,0X4010L,0X40000L,0X40010L,0X44000L,0X44010L,
  2457. 0X100L,0X110L,0X4100L,0X4110L,0X40100L,0X40110L,0X44100L,0X44110L,
  2458. 0X20000L,0X20010L,0X24000L,0X24010L,0X60000L,0X60010L,0X64000L,0X64010L,
  2459. 0X20100L,0X20110L,0X24100L,0X24110L,0X60100L,0X60110L,0X64100L,0X64110L,
  2460. 0X1L,0X11L,0X4001L,0X4011L,0X40001L,0X40011L,0X44001L,0X44011L,
  2461. 0X101L,0X111L,0X4101L,0X4111L,0X40101L,0X40111L,0X44101L,0X44111L,
  2462. 0X20001L,0X20011L,0X24001L,0X24011L,0X60001L,0X60011L,0X64001L,0X64011L,
  2463. 0X20101L,0X20111L,0X24101L,0X24111L,0X60101L,0X60111L,0X64101L,0X64111L,
  2464. 0X80000L,0X80010L,0X84000L,0X84010L,0XC0000L,0XC0010L,0XC4000L,0XC4010L,
  2465. 0X80100L,0X80110L,0X84100L,0X84110L,0XC0100L,0XC0110L,0XC4100L,0XC4110L,
  2466. 0XA0000L,0XA0010L,0XA4000L,0XA4010L,0XE0000L,0XE0010L,0XE4000L,0XE4010L,
  2467. 0XA0100L,0XA0110L,0XA4100L,0XA4110L,0XE0100L,0XE0110L,0XE4100L,0XE4110L,
  2468. 0X80001L,0X80011L,0X84001L,0X84011L,0XC0001L,0XC0011L,0XC4001L,0XC4011L,
  2469. 0X80101L,0X80111L,0X84101L,0X84111L,0XC0101L,0XC0111L,0XC4101L,0XC4111L,
  2470. 0XA0001L,0XA0011L,0XA4001L,0XA4011L,0XE0001L,0XE0011L,0XE4001L,0XE4011L,
  2471. 0XA0101L,0XA0111L,0XA4101L,0XA4111L,0XE0101L,0XE0111L,0XE4101L,0XE4111L,
  2472.  
  2473. 0X0L,0X800000L,0X2L,0X800002L,0X200L,0X800200L,0X202L,0X800202L,
  2474. 0X200000L,0XA00000L,0X200002L,0XA00002L,0X200200L,0XA00200L,0X200202L,0XA00202L,
  2475. 0X1000L,0X801000L,0X1002L,0X801002L,0X1200L,0X801200L,0X1202L,0X801202L,
  2476. 0X201000L,0XA01000L,0X201002L,0XA01002L,0X201200L,0XA01200L,0X201202L,0XA01202L,
  2477. 0X0L,0X800000L,0X2L,0X800002L,0X200L,0X800200L,0X202L,0X800202L,
  2478. 0X200000L,0XA00000L,0X200002L,0XA00002L,0X200200L,0XA00200L,0X200202L,0XA00202L,
  2479. 0X1000L,0X801000L,0X1002L,0X801002L,0X1200L,0X801200L,0X1202L,0X801202L,
  2480. 0X201000L,0XA01000L,0X201002L,0XA01002L,0X201200L,0XA01200L,0X201202L,0XA01202L,
  2481. 0X40L,0X800040L,0X42L,0X800042L,0X240L,0X800240L,0X242L,0X800242L,
  2482. 0X200040L,0XA00040L,0X200042L,0XA00042L,0X200240L,0XA00240L,0X200242L,0XA00242L,
  2483. 0X1040L,0X801040L,0X1042L,0X801042L,0X1240L,0X801240L,0X1242L,0X801242L,
  2484. 0X201040L,0XA01040L,0X201042L,0XA01042L,0X201240L,0XA01240L,0X201242L,0XA01242L,
  2485. 0X40L,0X800040L,0X42L,0X800042L,0X240L,0X800240L,0X242L,0X800242L,
  2486. 0X200040L,0XA00040L,0X200042L,0XA00042L,0X200240L,0XA00240L,0X200242L,0XA00242L,
  2487. 0X1040L,0X801040L,0X1042L,0X801042L,0X1240L,0X801240L,0X1242L,0X801242L,
  2488. 0X201040L,0XA01040L,0X201042L,0XA01042L,0X201240L,0XA01240L,0X201242L,0XA01242L,
  2489.  
  2490. 0X0L,0X2000L,0X4L,0X2004L,0X400L,0X2400L,0X404L,0X2404L,
  2491. 0X0L,0X2000L,0X4L,0X2004L,0X400L,0X2400L,0X404L,0X2404L,
  2492. 0X400000L,0X402000L,0X400004L,0X402004L,0X400400L,0X402400L,0X400404L,0X402404L,
  2493. 0X400000L,0X402000L,0X400004L,0X402004L,0X400400L,0X402400L,0X400404L,0X402404L,
  2494. 0X20L,0X2020L,0X24L,0X2024L,0X420L,0X2420L,0X424L,0X2424L,
  2495. 0X20L,0X2020L,0X24L,0X2024L,0X420L,0X2420L,0X424L,0X2424L,
  2496. 0X400020L,0X402020L,0X400024L,0X402024L,0X400420L,0X402420L,0X400424L,0X402424L,
  2497. 0X400020L,0X402020L,0X400024L,0X402024L,0X400420L,0X402420L,0X400424L,0X402424L,
  2498. 0X8000L,0XA000L,0X8004L,0XA004L,0X8400L,0XA400L,0X8404L,0XA404L,
  2499. 0X8000L,0XA000L,0X8004L,0XA004L,0X8400L,0XA400L,0X8404L,0XA404L,
  2500. 0X408000L,0X40A000L,0X408004L,0X40A004L,0X408400L,0X40A400L,0X408404L,0X40A404L,
  2501. 0X408000L,0X40A000L,0X408004L,0X40A004L,0X408400L,0X40A400L,0X408404L,0X40A404L,
  2502. 0X8020L,0XA020L,0X8024L,0XA024L,0X8420L,0XA420L,0X8424L,0XA424L,
  2503. 0X8020L,0XA020L,0X8024L,0XA024L,0X8420L,0XA420L,0X8424L,0XA424L,
  2504. 0X408020L,0X40A020L,0X408024L,0X40A024L,0X408420L,0X40A420L,0X408424L,0X40A424L,
  2505. 0X408020L,0X40A020L,0X408024L,0X40A024L,0X408420L,0X40A420L,0X408424L,0X40A424L,
  2506.  
  2507. 0X0L,0X10000L,0X8L,0X10008L,0X80L,0X10080L,0X88L,0X10088L,
  2508. 0X0L,0X10000L,0X8L,0X10008L,0X80L,0X10080L,0X88L,0X10088L,
  2509. 0X100000L,0X110000L,0X100008L,0X110008L,0X100080L,0X110080L,0X100088L,0X110088L,
  2510. 0X100000L,0X110000L,0X100008L,0X110008L,0X100080L,0X110080L,0X100088L,0X110088L,
  2511. 0X800L,0X10800L,0X808L,0X10808L,0X880L,0X10880L,0X888L,0X10888L,
  2512. 0X800L,0X10800L,0X808L,0X10808L,0X880L,0X10880L,0X888L,0X10888L,
  2513. 0X100800L,0X110800L,0X100808L,0X110808L,0X100880L,0X110880L,0X100888L,0X110888L,
  2514. 0X100800L,0X110800L,0X100808L,0X110808L,0X100880L,0X110880L,0X100888L,0X110888L,
  2515. 0X0L,0X10000L,0X8L,0X10008L,0X80L,0X10080L,0X88L,0X10088L,
  2516. 0X0L,0X10000L,0X8L,0X10008L,0X80L,0X10080L,0X88L,0X10088L,
  2517. 0X100000L,0X110000L,0X100008L,0X110008L,0X100080L,0X110080L,0X100088L,0X110088L,
  2518. 0X100000L,0X110000L,0X100008L,0X110008L,0X100080L,0X110080L,0X100088L,0X110088L,
  2519. 0X800L,0X10800L,0X808L,0X10808L,0X880L,0X10880L,0X888L,0X10888L,
  2520. 0X800L,0X10800L,0X808L,0X10808L,0X880L,0X10880L,0X888L,0X10888L,
  2521. 0X100800L,0X110800L,0X100808L,0X110808L,0X100880L,0X110880L,0X100888L,0X110888L,
  2522. 0X100800L,0X110800L,0X100808L,0X110808L,0X100880L,0X110880L,0X100888L,0X110888L,
  2523.  
  2524. 0X0L,0X0L,0X80L,0X80L,0X2000L,0X2000L,0X2080L,0X2080L,
  2525. 0X1L,0X1L,0X81L,0X81L,0X2001L,0X2001L,0X2081L,0X2081L,
  2526. 0X200000L,0X200000L,0X200080L,0X200080L,0X202000L,0X202000L,0X202080L,0X202080L,
  2527. 0X200001L,0X200001L,0X200081L,0X200081L,0X202001L,0X202001L,0X202081L,0X202081L,
  2528. 0X20000L,0X20000L,0X20080L,0X20080L,0X22000L,0X22000L,0X22080L,0X22080L,
  2529. 0X20001L,0X20001L,0X20081L,0X20081L,0X22001L,0X22001L,0X22081L,0X22081L,
  2530. 0X220000L,0X220000L,0X220080L,0X220080L,0X222000L,0X222000L,0X222080L,0X222080L,
  2531. 0X220001L,0X220001L,0X220081L,0X220081L,0X222001L,0X222001L,0X222081L,0X222081L,
  2532. 0X2L,0X2L,0X82L,0X82L,0X2002L,0X2002L,0X2082L,0X2082L,
  2533. 0X3L,0X3L,0X83L,0X83L,0X2003L,0X2003L,0X2083L,0X2083L,
  2534. 0X200002L,0X200002L,0X200082L,0X200082L,0X202002L,0X202002L,0X202082L,0X202082L,
  2535. 0X200003L,0X200003L,0X200083L,0X200083L,0X202003L,0X202003L,0X202083L,0X202083L,
  2536. 0X20002L,0X20002L,0X20082L,0X20082L,0X22002L,0X22002L,0X22082L,0X22082L,
  2537. 0X20003L,0X20003L,0X20083L,0X20083L,0X22003L,0X22003L,0X22083L,0X22083L,
  2538. 0X220002L,0X220002L,0X220082L,0X220082L,0X222002L,0X222002L,0X222082L,0X222082L,
  2539. 0X220003L,0X220003L,0X220083L,0X220083L,0X222003L,0X222003L,0X222083L,0X222083L,
  2540.  
  2541. 0X0L,0X10L,0X800000L,0X800010L,0X10000L,0X10010L,0X810000L,0X810010L,
  2542. 0X200L,0X210L,0X800200L,0X800210L,0X10200L,0X10210L,0X810200L,0X810210L,
  2543. 0X0L,0X10L,0X800000L,0X800010L,0X10000L,0X10010L,0X810000L,0X810010L,
  2544. 0X200L,0X210L,0X800200L,0X800210L,0X10200L,0X10210L,0X810200L,0X810210L,
  2545. 0X100000L,0X100010L,0X900000L,0X900010L,0X110000L,0X110010L,0X910000L,0X910010L,
  2546. 0X100200L,0X100210L,0X900200L,0X900210L,0X110200L,0X110210L,0X910200L,0X910210L,
  2547. 0X100000L,0X100010L,0X900000L,0X900010L,0X110000L,0X110010L,0X910000L,0X910010L,
  2548. 0X100200L,0X100210L,0X900200L,0X900210L,0X110200L,0X110210L,0X910200L,0X910210L,
  2549. 0X4L,0X14L,0X800004L,0X800014L,0X10004L,0X10014L,0X810004L,0X810014L,
  2550. 0X204L,0X214L,0X800204L,0X800214L,0X10204L,0X10214L,0X810204L,0X810214L,
  2551. 0X4L,0X14L,0X800004L,0X800014L,0X10004L,0X10014L,0X810004L,0X810014L,
  2552. 0X204L,0X214L,0X800204L,0X800214L,0X10204L,0X10214L,0X810204L,0X810214L,
  2553. 0X100004L,0X100014L,0X900004L,0X900014L,0X110004L,0X110014L,0X910004L,0X910014L,
  2554. 0X100204L,0X100214L,0X900204L,0X900214L,0X110204L,0X110214L,0X910204L,0X910214L,
  2555. 0X100004L,0X100014L,0X900004L,0X900014L,0X110004L,0X110014L,0X910004L,0X910014L,
  2556. 0X100204L,0X100214L,0X900204L,0X900214L,0X110204L,0X110214L,0X910204L,0X910214L,
  2557.  
  2558. 0X0L,0X400L,0X1000L,0X1400L,0X80000L,0X80400L,0X81000L,0X81400L,
  2559. 0X20L,0X420L,0X1020L,0X1420L,0X80020L,0X80420L,0X81020L,0X81420L,
  2560. 0X4000L,0X4400L,0X5000L,0X5400L,0X84000L,0X84400L,0X85000L,0X85400L,
  2561. 0X4020L,0X4420L,0X5020L,0X5420L,0X84020L,0X84420L,0X85020L,0X85420L,
  2562. 0X800L,0XC00L,0X1800L,0X1C00L,0X80800L,0X80C00L,0X81800L,0X81C00L,
  2563. 0X820L,0XC20L,0X1820L,0X1C20L,0X80820L,0X80C20L,0X81820L,0X81C20L,
  2564. 0X4800L,0X4C00L,0X5800L,0X5C00L,0X84800L,0X84C00L,0X85800L,0X85C00L,
  2565. 0X4820L,0X4C20L,0X5820L,0X5C20L,0X84820L,0X84C20L,0X85820L,0X85C20L,
  2566. 0X0L,0X400L,0X1000L,0X1400L,0X80000L,0X80400L,0X81000L,0X81400L,
  2567. 0X20L,0X420L,0X1020L,0X1420L,0X80020L,0X80420L,0X81020L,0X81420L,
  2568. 0X4000L,0X4400L,0X5000L,0X5400L,0X84000L,0X84400L,0X85000L,0X85400L,
  2569. 0X4020L,0X4420L,0X5020L,0X5420L,0X84020L,0X84420L,0X85020L,0X85420L,
  2570. 0X800L,0XC00L,0X1800L,0X1C00L,0X80800L,0X80C00L,0X81800L,0X81C00L,
  2571. 0X820L,0XC20L,0X1820L,0X1C20L,0X80820L,0X80C20L,0X81820L,0X81C20L,
  2572. 0X4800L,0X4C00L,0X5800L,0X5C00L,0X84800L,0X84C00L,0X85800L,0X85C00L,
  2573. 0X4820L,0X4C20L,0X5820L,0X5C20L,0X84820L,0X84C20L,0X85820L,0X85C20L,
  2574.  
  2575. 0X0L,0X100L,0X40000L,0X40100L,0X0L,0X100L,0X40000L,0X40100L,
  2576. 0X40L,0X140L,0X40040L,0X40140L,0X40L,0X140L,0X40040L,0X40140L,
  2577. 0X400000L,0X400100L,0X440000L,0X440100L,0X400000L,0X400100L,0X440000L,0X440100L,
  2578. 0X400040L,0X400140L,0X440040L,0X440140L,0X400040L,0X400140L,0X440040L,0X440140L,
  2579. 0X8000L,0X8100L,0X48000L,0X48100L,0X8000L,0X8100L,0X48000L,0X48100L,
  2580. 0X8040L,0X8140L,0X48040L,0X48140L,0X8040L,0X8140L,0X48040L,0X48140L,
  2581. 0X408000L,0X408100L,0X448000L,0X448100L,0X408000L,0X408100L,0X448000L,0X448100L,
  2582. 0X408040L,0X408140L,0X448040L,0X448140L,0X408040L,0X408140L,0X448040L,0X448140L,
  2583. 0X8L,0X108L,0X40008L,0X40108L,0X8L,0X108L,0X40008L,0X40108L,
  2584. 0X48L,0X148L,0X40048L,0X40148L,0X48L,0X148L,0X40048L,0X40148L,
  2585. 0X400008L,0X400108L,0X440008L,0X440108L,0X400008L,0X400108L,0X440008L,0X440108L,
  2586. 0X400048L,0X400148L,0X440048L,0X440148L,0X400048L,0X400148L,0X440048L,0X440148L,
  2587. 0X8008L,0X8108L,0X48008L,0X48108L,0X8008L,0X8108L,0X48008L,0X48108L,
  2588. 0X8048L,0X8148L,0X48048L,0X48148L,0X8048L,0X8148L,0X48048L,0X48148L,
  2589. 0X408008L,0X408108L,0X448008L,0X448108L,0X408008L,0X408108L,0X448008L,0X448108L,
  2590. 0X408048L,0X408148L,0X448048L,0X448148L,0X408048L,0X408148L,0X448048L,0X448148L 
  2591. };
  2592.  
  2593. /* --- some bit manipulation primitives --- */
  2594.  
  2595. /* g_keybit -- extract bit bnum from the key in inkey */
  2596. #define g_keybit(bnum) (01 & (inkey [bnum/8] >> (8 - (bnum%8))))
  2597.  
  2598. long    lrot28 (lval)
  2599. /* do left rotate of 28 bit quantity */
  2600. long    lval;
  2601. {
  2602.   lval <<= 1;
  2603.   if (0X10000000L & lval) lval++;
  2604.   lval &= 0XFFFFFFFL;
  2605.   return (lval);
  2606. }
  2607.  
  2608. /* --- following code and data does key schedule generation --- */
  2609.  
  2610. #define SUCCESS 0       /* return codes for ksmake */
  2611. #define FAILURE SUCCESS + 1
  2612.  
  2613. int ksmake (inkey,ks)       /* Make a key schedule from key bytes in inkey */
  2614. unsigned inkey [8];
  2615. unsigned ks [16] [4];
  2616. {
  2617.   extern long pc2otab [8] [128];
  2618.  
  2619.   int   round;
  2620.   long  pcct, pcdt;
  2621.   long  pc2out [2];
  2622.   int   i, j, parac;
  2623.   unsigned incopy;
  2624.  
  2625.   /* test parity of bytes in inkey */
  2626.   for (i = 0; i < 8; i++)       /* do each byte */
  2627.   {
  2628.     parac = 0;
  2629.     incopy = inkey [i];
  2630.  
  2631.     for (j = 0; j < 8; j++)     /* 8 bits in a DES byte */
  2632.     {
  2633.       if (incopy & 01) parac++;
  2634.       incopy >>= 1;
  2635.     }
  2636.     if (! (parac & 01)) return (FAILURE); /* no odd parity on this byte */
  2637.   }
  2638.  
  2639.   /* do pc-1 permutation, extracting bits from inkey */
  2640.   pcct = pcdt = 0L;
  2641.   for (i = 0; i < 27; i++)   
  2642.    /* filling all appropriate bits */
  2643.   {
  2644.     pcct |= g_keybit(pc1c [i]);
  2645.     pcdt |= g_keybit(pc1d [i]);
  2646.     pcct <<= 1;
  2647.     pcdt <<= 1;
  2648.   }
  2649.   /* one final ior, without a shift */
  2650.   pcct |= g_keybit(pc1c [i]);
  2651.   pcdt |= g_keybit(pc1d [i]);
  2652.  
  2653.   for (round = 0; round < 16; round++)
  2654.   {
  2655.     /* always at least one shift */
  2656.     pcct = lrot28 (pcct);
  2657.     pcdt = lrot28 (pcdt);
  2658.  
  2659.     if (shiftsked [round] == 2)
  2660.     {   /* this round needs another shift */
  2661.       pcct = lrot28 (pcct);
  2662.       pcdt = lrot28 (pcdt);
  2663.     } 
  2664.  
  2665.     /* Now, pcct and pcdt have the values on which we can apply
  2666.        pc2 and select the key bits, storing them in pc2out[0] and
  2667.        pc2out[1]. The high order [pc2out[0]] bits all come from
  2668.        pcct, and the low order from pcdt. */
  2669.  
  2670.     pc2out [0] = pc2otab [0] [pcct >> 21];
  2671.     pc2out [0] |= pc2otab [1] [0X7F & (pcct >> 14)];
  2672.     pc2out [0] |= pc2otab [2] [0X7F & (pcct >> 7)];
  2673.     pc2out [0] |= pc2otab [3] [0X7F & pcct];
  2674.  
  2675.     pc2out [1] = pc2otab [4] [pcdt >> 21];
  2676.     pc2out [1] |= pc2otab [5] [0X7F & (pcdt >> 14)];
  2677.     pc2out [1] |= pc2otab [6] [0X7F & (pcdt >> 7)];
  2678.     pc2out [1] |= pc2otab [7] [0X7F & pcdt];
  2679.  
  2680.     /* order key bits and bytes so as to be compatible with
  2681.        the format generated by the E implementation */
  2682.  
  2683.     ks [round] [0] = 0XFC00 & (pc2out [0] >> 8);
  2684.     ks [round] [0] |= (0XFC & (pc2out [0] >> 4));
  2685.     ks [round] [1] = 0XFC00 & (pc2out [1] >> 8);
  2686.     ks [round] [1] |= (0XFC & (pc2out [1] >> 4));
  2687.  
  2688.     ks [round] [2] = 0XFC00 & (pc2out [0] >> 2);
  2689.     ks [round] [2] |= (0XFC & (pc2out [0] << 2));
  2690.     ks [round] [3] = 0XFC00 & (pc2out [1] >> 2);
  2691.     ks [round] [3] |= (0XFC & (pc2out [1] << 2));
  2692.   }
  2693.   return (SUCCESS);
  2694. }
  2695.  
  2696. #define LMASK    0XFCFCFCFCL;
  2697.  
  2698. /* doip -- permute 64 bits from inar to outar */
  2699. doip (inar, outar)      
  2700. long    inar [2];
  2701. long    outar [2];
  2702. {
  2703.   long lt;
  2704.  
  2705.   outar [0] = inar [0];
  2706.   outar [1] = inar [1];
  2707.   EXSHMSK(outar[1],0x0f0f0f0f,outar[0],4,lt);
  2708.   EXSHMSK(outar[1],0x0000ffff,outar[0],16,lt);
  2709.   EXSHMSK(outar[0],0x33333333,outar[1],2,lt);
  2710.   EXSHMSK(outar[0],0x00ff00ff,outar[1],8,lt);
  2711.   EXSHMSK(outar[1],0x55555555,outar[0],1,lt);
  2712. }
  2713.  
  2714. /* doipi -- perform ip-inverse */
  2715. doipi (inar, outar)     
  2716. long    inar [2];
  2717. long    outar [2];
  2718. {
  2719.   long lt;
  2720.  
  2721.   outar [0] = inar [0];
  2722.   outar [1] = inar [1];
  2723.   EXSHMSK(outar[1],0x55555555,outar[0],1,lt);
  2724.   EXSHMSK(outar[0],0x00ff00ff,outar[1],8,lt);
  2725.   EXSHMSK(outar[0],0x33333333,outar[1],2,lt);
  2726.   EXSHMSK(outar[1],0x0000ffff,outar[0],16,lt);
  2727.   EXSHMSK(outar[1],0x0f0f0f0f,outar[0],4,lt);
  2728. }
  2729.  
  2730. /* des_encrypt -- encrypt a block under key sched in ks */
  2731. des_encrypt (inar, outar, ks)   
  2732. long    inar [2];
  2733. long    outar [2];
  2734. unsigned        ks [16] [4];
  2735. {
  2736.   extern long snop [8] [64];
  2737.  
  2738.   register int round, oddbit;
  2739.   unsigned expan [4];   /* receives output of E transform */
  2740.   long sbout, scopy, tlong;
  2741.   long oarr [2];
  2742.  
  2743.   doip (inar, outar);
  2744.  
  2745.   for (round = 0; round < 16; round++)
  2746.   {
  2747.     sbout = 0L;
  2748.  
  2749.     tlong = outar [1];
  2750.     oddbit = (int) (01 & tlong);
  2751.     tlong >>= 1;
  2752.     tlong &= 0X7FFFFFFFL;       /* defeat sign extend -- jl 17 feb 84 */
  2753.     if (oddbit) tlong |= 0X80000000L;
  2754.  
  2755.     tlong &= LMASK;
  2756.     expan [0] = (unsigned) (tlong >> 16);
  2757.     expan [1] = (unsigned) tlong;
  2758.  
  2759.     tlong = outar [1];
  2760.     oddbit = !! (tlong & 0X80000000L);
  2761.     tlong <<= 3;
  2762.     if (oddbit) tlong |= 04;
  2763.     tlong &= LMASK;
  2764.     expan [2] = (unsigned) (tlong >> 16);
  2765.     expan [3] = (unsigned) tlong;
  2766.  
  2767.     /* this code bypasses the alternative of loop setup 
  2768.        and resultant computation within the loop for speed */
  2769.     expan [0] ^= ks [round] [0];
  2770.     sbout |= snop [0] [0X3F & (expan [0] >> 10)];
  2771.     sbout |= snop [1] [0X3F & (expan [0] >> 2)];
  2772.     expan [1] ^= ks [round] [1];
  2773.     sbout |= snop [2] [0X3F & (expan [1] >> 10)];
  2774.     sbout |= snop [3] [0X3F & (expan [1] >> 2)];
  2775.     expan [2] ^= ks [round] [2];
  2776.     sbout |= snop [4] [0X3F & (expan [2] >> 10)];
  2777.     sbout |= snop [5] [0X3F & (expan [2] >> 2)];
  2778.     expan [3] ^= ks [round] [3];
  2779.     sbout |= snop [6] [0X3F & (expan [3] >> 10)];
  2780.     sbout |= snop [7] [0X3F & (expan [3] >> 2)];
  2781.  
  2782.     scopy = outar [0];
  2783.     outar [0] = outar [1];
  2784.     outar [1] = scopy ^ sbout;
  2785.   }
  2786.  
  2787.   /* a final swap */
  2788.   scopy = outar [0];
  2789.   outar [0] = outar [1];
  2790.   outar [1] = scopy;
  2791.  
  2792.   doipi (outar, oarr);  /* perform ip-inverse into temp copy */
  2793.   outar [0] = oarr [0];
  2794.   outar [1] = oarr [1];
  2795. }
  2796.  
  2797. /* des_decrypt -- decrypt a block under key sched in ks */
  2798. /* not used as of 5 May, but retained for completeness */
  2799.  
  2800. des_decrypt (inar, outar, ks)   
  2801. long    inar [2];
  2802. long    outar [2];
  2803. unsigned ks [16] [4];
  2804. {
  2805.   extern long snop [8] [64];
  2806.  
  2807.   register int round, oddbit;
  2808.   unsigned expan [4];   /* receives output of E transform */
  2809.   long sbout, scopy, tlong;
  2810.   long oarr [2];
  2811.  
  2812.   doip (inar, outar);
  2813.  
  2814.   for (round = 15; round >= 0; round--)
  2815.   /* note that decryption selects schedule keys in opposite order */
  2816.   {
  2817.     sbout = 0L;
  2818.  
  2819.     tlong = outar [1];
  2820.     oddbit = (int) (01 & tlong);
  2821.     tlong >>= 1;
  2822.     tlong &= 0X7FFFFFFFL;       /* defeat sign extend -- jl 17 feb 84 */
  2823.     if (oddbit) tlong |= 0X80000000L;
  2824.  
  2825.     tlong &= LMASK;
  2826.     expan [0] = (unsigned) (tlong >> 16);
  2827.     expan [1] = (unsigned) tlong;
  2828.  
  2829.     tlong = outar [1];
  2830.     oddbit = !! (tlong & 0X80000000L);
  2831.     tlong <<= 3;
  2832.     if (oddbit) tlong |= 04;
  2833.     tlong &= LMASK;
  2834.     expan [2] = (unsigned) (tlong >> 16);
  2835.     expan [3] = (unsigned) tlong;
  2836.  
  2837.     /* this code bypasses the alternative of loop setup 
  2838.        and resultant computation within the loop for speed */
  2839.     expan [0] ^= ks [round] [0];
  2840.     sbout |= snop [0] [0X3F & (expan [0] >> 10)];
  2841.     sbout |= snop [1] [0X3F & (expan [0] >> 2)];
  2842.     expan [1] ^= ks [round] [1];
  2843.     sbout |= snop [2] [0X3F & (expan [1] >> 10)];
  2844.     sbout |= snop [3] [0X3F & (expan [1] >> 2)];
  2845.     expan [2] ^= ks [round] [2];
  2846.     sbout |= snop [4] [0X3F & (expan [2] >> 10)];
  2847.     sbout |= snop [5] [0X3F & (expan [2] >> 2)];
  2848.     expan [3] ^= ks [round] [3];
  2849.     sbout |= snop [6] [0X3F & (expan [3] >> 10)];
  2850.     sbout |= snop [7] [0X3F & (expan [3] >> 2)];
  2851.  
  2852.     scopy = outar [0];
  2853.     outar [0] = outar [1];
  2854.     outar [1] = scopy ^ sbout;
  2855.   }
  2856.  
  2857.   /* a final swap */
  2858.   scopy = outar [0];
  2859.   outar [0] = outar [1];
  2860.   outar [1] = scopy;
  2861.  
  2862.   doipi (outar, oarr);  /* perform ip-inverse into temp copy */
  2863.   outar [0] = oarr [0];
  2864.   outar [1] = oarr [1];
  2865. }
  2866. /* support routines for demodes */
  2867.  
  2868. /* read input bytes from stdin */
  2869. int     g_inbytes (nby, buffer)     /* returns TRUE iff EOF reached */
  2870. int     nby;        /* number of bytes needed at a time */
  2871.             /* if insufficient, will be padded with nulls */
  2872. char    buffer [];
  2873. {
  2874.   int   bufix;
  2875.   int   getcval;
  2876.  
  2877.   /* init all significant bytes to null pad */
  2878.   for (bufix = 0; bufix < nby; bufix++) buffer[bufix] = 0;
  2879.  
  2880.   for (bufix = 0; bufix < nby; bufix++)
  2881.   {
  2882.     getcval = getchar ();
  2883.     buffer [bufix] = (char) getcval;
  2884.     if (getcval == EOF)
  2885.     {
  2886.       buffer[bufix] = 0;        /* replace with pad */
  2887.       return (TRUE);            /* indicating that EOF detected */
  2888.     }
  2889.   }
  2890.   return (FALSE);       /* indicating no EOF detected */
  2891. }
  2892.  
  2893. /* represent a series of bytes (conditionally) in two buffers, as
  2894.    printable representation and hex representation */
  2895. di_bytes (nby, inbuf, pr_buf, hx_buf)
  2896. int     nby;
  2897. char    inbuf [];
  2898. char    pr_buf [];      /* NULL if not desired */
  2899. char    hx_buf [];      /* NULL if not desired */
  2900. {
  2901.   int i;
  2902.  
  2903.   for (i = 0; i < nby; i++)
  2904.   {
  2905.     if (pr_buf != NULL)
  2906.     {
  2907.       /* Try to show as a printable character, either directly or */
  2908.       /* by masking off the MSB (if the latter, prefix with '#') */
  2909.       if (inbuf [i] > 0x7f)
  2910.       {
  2911.     if (isprint (inbuf [i] & 0x7f))
  2912.       sprintf (pr_buf, "#%c", inbuf [i] & 0x7f);
  2913.     else sprintf (pr_buf, "  ");
  2914.       }
  2915.       else
  2916.       {
  2917.     if (isprint (inbuf [i]))
  2918.       sprintf (pr_buf, " %c", inbuf [i]);
  2919.     else sprintf (pr_buf, "  ");
  2920.       }
  2921.       pr_buf += 2;
  2922.     }
  2923.     if (hx_buf != NULL)
  2924.     {
  2925.       sprintf (hx_buf, "%1x%1x", 0xf & (inbuf[i]>>4),0xf & inbuf [i]);
  2926.       hx_buf += 2;
  2927.     }
  2928.   }
  2929.   if (pr_buf != NULL) sprintf (pr_buf, "|");
  2930.   if (hx_buf != NULL) sprintf (hx_buf, "|");
  2931. }
  2932.  
  2933. packbtol (as_ba, as_l)   /* pack 4 bytes into a long */
  2934. char    as_ba [];
  2935. long    *as_l;
  2936. {
  2937.   long lt;
  2938.  
  2939.   lt = as_ba [0] & 0xff;
  2940.   lt <<= 8;
  2941.   lt |= as_ba [1] & 0xff;
  2942.   lt <<= 8;
  2943.   lt |= as_ba [2] & 0xff;
  2944.   lt <<= 8;
  2945.   lt |= as_ba [3] & 0xff;
  2946.  
  2947.   *as_l = lt;
  2948. }
  2949.  
  2950. sprdltob (as_l, as_ba)  /* spread a long into 4 bytes */
  2951. long    as_l;
  2952. char    as_ba [];
  2953. {
  2954.   as_ba [0] = (char) ((as_l >> 24) & 0xff);
  2955.   as_ba [1] = (char) ((as_l >> 16) & 0xff);
  2956.   as_ba [2] = (char) ((as_l >> 8) & 0xff);
  2957.   as_ba [3] = (char) (as_l & 0xff);
  2958. }
  2959.  
  2960. lsh64 (lar, count)      /* left shift a 64-bit quantity maintained */
  2961. long    lar[];          /* in a 2-element long array. Assumes that */
  2962. int     count;          /* a long has at least 32 bits */
  2963. {
  2964.   int   i; 
  2965.   long  t;
  2966.  
  2967.   for (i = 0; i < count; i++)
  2968.   {
  2969.     t = (lar [1] >> 31) & 0x1l;
  2970.     lar [1] <<= 1;
  2971.     lar [0] <<= 1;
  2972.     lar [0] |= t;
  2973.   }  
  2974.   lar [0] &= 0xffffffffl;
  2975.   lar [1] &= 0xffffffffl;
  2976. }
  2977.  
  2978. rsh64 (lar, count)      /* right shift a 64-bit quantity maintained */
  2979. long    lar[];          /* in a 2-element long array. Assumes that */
  2980. int     count;          /* a long has at least 32 bits */
  2981. {
  2982.   int   i; 
  2983.   long  t;
  2984.  
  2985.   for (i = 0; i < count; i++)
  2986.   {
  2987.     t = lar [0] & 0x1l;
  2988.     lar [1] >>= 1;
  2989.     lar [0] >>= 1;
  2990.     lar [1] |= (t << 31);
  2991.   }  
  2992. }
  2993.  
  2994. rplr64 (base, modr, nbits)      /* replace rightmost nbits of base */
  2995. long    base[];                 /* (64-bit qty in 2-elmt long array) */
  2996. long    modr[];                 /* with corresponding bits from modr */
  2997. int     nbits;
  2998. {       /* works on architectures where a long is 32 bits or more */
  2999.   long  mask;
  3000.   long  lmod;   /* local copy of modr word */
  3001.  
  3002.   mask = (nbits >= 32) ? 0xffffffffl : ((0x1l << nbits) - 1);
  3003. /*  mask = (0x1l << ((nbits > 32) ? 32 : nbits)) - 1; */
  3004.   base [1] &= ~mask;    /* wipe out existing low bits */
  3005.   lmod = modr [1] & mask;
  3006.   base [1] |= lmod;
  3007.  
  3008.   nbits -= 32;
  3009.   if (nbits <= 0) return;
  3010.   
  3011.   mask = (0x1l << nbits) - 1;
  3012.   base [0] &= ~mask;
  3013.   lmod = modr [0] & mask;
  3014.   base [0] |= lmod;
  3015. }
  3016.  
  3017. cpy64 (src, dest)       /* copy src 2-elmt long array to dest */
  3018. long    src[];
  3019. long    dest[];
  3020. {
  3021.   dest [0] = src [0];
  3022.   dest [1] = src [1];
  3023. }
  3024.  
  3025. #ifndef TIMEONLY
  3026. main (argc,argv)
  3027. int     argc;
  3028. char    *argv [];
  3029. {
  3030.   int   argn;
  3031.   int   dmode;
  3032.   int   eofyet = FALSE; /* will set to TRUE when end of input */
  3033.   int   quant = 0;      /* quantum size (in bits) for selected mode */
  3034.   int   flwid;          /* size to display a 64-bit chunk of pt or ct */
  3035.   int   i, j;
  3036.   long  iv [2], keyl [2];
  3037.  
  3038.   unsigned      inkey [8];
  3039.   char  inkeyc [8]; 
  3040.   char  inbbuf [8], otbbuf [8];
  3041.   char  iprline [80], ihxline [80], ohxline [80];
  3042.   unsigned      ks [16] [4];
  3043.  
  3044.   long plain [2], crypt [2], cprbuf [2], cipher [2];
  3045.  
  3046.   /* default key and IV to NBS sample values */
  3047.   keyl [0] = 0x01234567l;
  3048.   keyl [1] = 0x89abcdefl;
  3049.   iv [0] = 0x12345678l;
  3050.   iv [1] = 0x90abcdefl;
  3051.  
  3052.   /* scan the command line */
  3053.   for (argn = 1; argn <= argc; argn++)
  3054.   {
  3055.     if (seq_nocase (argv[argn], "-m")) /* mode specifier */
  3056.     {  /* one string argument expected */
  3057.       argn++;
  3058.       if (seq_nocase (argv[argn], "ecb")) 
  3059.       {
  3060.         dmode = ECB; quant = 64;
  3061.       }
  3062.       else if (seq_nocase (argv[argn], "cbc")) 
  3063.       {
  3064.         dmode = CBC; quant = 64;
  3065.       }
  3066.       else if (seq_nocase (argv[argn], "ofb")) 
  3067.       {
  3068.         dmode = OFB; if (quant == 0) quant = 64; /* may be overridden */
  3069.       }
  3070.       else if (seq_nocase (argv[argn], "cfb")) 
  3071.       {
  3072.         dmode = CFB; if (quant == 0) quant = 64; /* may be overridden */
  3073.       }
  3074.     }
  3075.     else if (seq_nocase (argv[argn], "-k"))    /* key specifier */
  3076.     {  /* two long hex numerics expected */
  3077.       argn++;
  3078.       sscanf (argv[argn], "%lx", &keyl [0]);
  3079.       argn++;
  3080.       sscanf (argv[argn], "%lx", &keyl [1]);
  3081.     }
  3082.     else if (seq_nocase (argv[argn], "-iv"))   /* IV specifier */
  3083.     {  /* two long hex numerics expected */
  3084.       argn++;
  3085.       sscanf (argv[argn], "%lx", &iv [0]);
  3086.       argn++;
  3087.       sscanf (argv[argn], "%lx", &iv [1]);
  3088.     }
  3089.     else if (seq_nocase (argv[argn], "-q"))     /* quantum specifier */
  3090.     { /* one decimal number expected */
  3091.       argn++;
  3092.       sscanf (argv[argn], "%d", &quant);
  3093.     }
  3094.   }
  3095.  
  3096.   if (((dmode == ECB) || (dmode == CBC)) && (quant != 64))
  3097.   {
  3098.     printf ("Can't override quantum of 64 for ECB or CBC modes... aborting\n");
  3099.     exit (1);
  3100.   }
  3101.  
  3102.   /* build key schedule (outside scanner, so default works) */
  3103.   sprdltob (keyl [0], & inkeyc [0]);
  3104.   sprdltob (keyl [1], & inkeyc [4]);
  3105.   for (i = 0; i < 8; i++) inkey [i] = (unsigned) (inkeyc [i] & 0xff);
  3106.   if (ksmake (inkey, ks) != SUCCESS)
  3107.   {
  3108.     printf ("Bad parity on key... aborting...\n");
  3109.     exit (1);
  3110.   }
  3111.  
  3112.   printf ("Mode is ");
  3113.   switch (dmode)
  3114.   {
  3115.     case ECB:
  3116.       printf ("ECB;");
  3117.       break;
  3118.     case CBC:
  3119.       printf ("CBC;");
  3120.       break;
  3121.     case OFB:
  3122.       printf ("OFB;");
  3123.       printf (" Quantum is %d;", quant);
  3124.       break;
  3125.     case CFB:
  3126.       printf ("CFB;");
  3127.       printf (" Quantum is %d;", quant);
  3128.       break;
  3129.     default:
  3130.       printf ("Unknown;");
  3131.       break;
  3132.   }
  3133.   printf (" Key is %lx %lx;", keyl [0], keyl [1]);
  3134.   if (dmode != ECB) printf (" IV is %lx %lx;", iv [0], iv [1]);
  3135.   printf ("\n");
  3136.  
  3137.   flwid = (8 * 2) + 1;      /* 8 bytes, 2 chars/byte, and a delimiter */
  3138.  
  3139.   while (eofyet == FALSE)       /* until EOF detected on input */
  3140.   {
  3141.     if (dmode == ECB)
  3142.     {
  3143.       for (i = 0; i < 4; i++)     /* 4 groups on a printable line */
  3144.       {
  3145.         if (TRUE == g_inbytes (8, inbbuf)) eofyet = TRUE;
  3146.         di_bytes (8, inbbuf, &iprline [flwid*i], &ihxline [flwid*i]);
  3147.         packbtol (&inbbuf[0], &plain[0]);
  3148.         packbtol (&inbbuf[4], &plain[1]);
  3149.         des_encrypt (plain, crypt, ks);
  3150.         sprdltob (crypt[0], &otbbuf[0]);
  3151.         sprdltob (crypt[1], &otbbuf[4]);
  3152.         di_bytes (8, otbbuf, NULL, &ohxline [flwid*i]);
  3153.     if (TRUE == eofyet) break;
  3154.       }
  3155.     }
  3156.     else if (dmode == CBC)
  3157.     {
  3158.       for (i = 0; i < 4; i++)     /* 4 groups on a printable line */
  3159.       {
  3160.         if (TRUE == g_inbytes (8, inbbuf)) eofyet = TRUE;
  3161.         di_bytes (8, inbbuf, &iprline [flwid*i], &ihxline [flwid*i]);
  3162.         packbtol (&inbbuf[0], &plain[0]);
  3163.         packbtol (&inbbuf[4], &plain[1]);
  3164.     plain [0] ^= iv [0];    /* XOR IV with input plaintext */
  3165.         plain [1] ^= iv [1];
  3166.         des_encrypt (plain, crypt, ks);
  3167.         sprdltob (crypt[0], &otbbuf[0]);
  3168.         sprdltob (crypt[1], &otbbuf[4]);
  3169.         di_bytes (8, otbbuf, NULL, &ohxline [flwid*i]);
  3170.     iv [0] = crypt [0];     /* use ciphertext output as next IV */
  3171.         iv [1] = crypt [1];
  3172.     if (TRUE == eofyet) break;
  3173.       }
  3174.     }
  3175.     else if (dmode == CFB)
  3176.     {
  3177.       for (i = 0; i < 4; i++)     /* 4 groups on a printable line */
  3178.       /* does file read and display in 64-bit units regardless of quantum */
  3179.       {
  3180.         if (TRUE == g_inbytes (8, inbbuf)) eofyet = TRUE;
  3181.         di_bytes (8, inbbuf, &iprline [flwid*i], &ihxline [flwid*i]);
  3182.         packbtol (&inbbuf[0], &plain[0]);
  3183.         packbtol (&inbbuf[4], &plain[1]);
  3184.     for (j = 0; j < 64; j+=quant)
  3185.     {
  3186.           des_encrypt (iv, crypt, ks);
  3187.       rsh64 (crypt, 64-quant);      /* right-align active DES output bits */
  3188.       cpy64 (plain, cprbuf);        /* copy plaintext to scratch */
  3189.       rsh64 (cprbuf, 64-(quant+j)); /* right-align active plaintext bits */
  3190.       /* XOR them into DES output */
  3191.       crypt [0] ^= cprbuf [0];  crypt [1] ^= cprbuf [1];
  3192.       lsh64 (iv, quant);            /* shift existing IV over */
  3193.       rplr64 (iv, crypt, quant);    /* replace LS IV bits with DES output */
  3194.       lsh64 (cipher, quant);        /* make space in cipher out array */
  3195.       rplr64 (cipher, crypt, quant); /* insert new output bits */
  3196.     }
  3197.         sprdltob (cipher[0], &otbbuf[0]);
  3198.         sprdltob (cipher[1], &otbbuf[4]);
  3199.         di_bytes (8, otbbuf, NULL, &ohxline [flwid*i]);
  3200.     if (TRUE == eofyet) break;
  3201.       }
  3202.     }
  3203.     else if (dmode == OFB)
  3204.     {
  3205.       for (i = 0; i < 4; i++)     /* 4 groups on a printable line */
  3206.       {
  3207.         if (TRUE == g_inbytes (8, inbbuf)) eofyet = TRUE;
  3208.         di_bytes (8, inbbuf, &iprline [flwid*i], &ihxline [flwid*i]);
  3209.         packbtol (&inbbuf[0], &plain[0]);
  3210.         packbtol (&inbbuf[4], &plain[1]);
  3211.     for (j = 0; j < 64; j+=quant)
  3212.     {
  3213.           des_encrypt (iv, crypt, ks);
  3214.       rsh64 (crypt, 64-quant);      /* right-align active DES output bits */
  3215.       lsh64 (iv, quant);            /* shift existing IV over */
  3216.       rplr64 (iv, crypt, quant);    /* replace LS IV bits with DES output */
  3217.       cpy64 (plain, cprbuf);        /* copy plaintext to scratch */
  3218.       rsh64 (cprbuf, 64-(quant+j)); /* right-align active plaintext bits */
  3219.       /* XOR them into DES output */
  3220.       crypt [0] ^= cprbuf [0];  crypt [1] ^= cprbuf [1];
  3221.       lsh64 (cipher, quant);        /* make space in cipher out array */
  3222.       rplr64 (cipher, crypt, quant); /* insert new output bits */
  3223.     }
  3224.         sprdltob (cipher[0], &otbbuf[0]);
  3225.         sprdltob (cipher[1], &otbbuf[4]);
  3226.     di_bytes (8, otbbuf, NULL, &ohxline [flwid*i]);
  3227.         if (TRUE == eofyet) break;
  3228.       }                      
  3229.     }
  3230.     printf ("%s\n%s\n%s\n", iprline, ihxline, ohxline);
  3231.   }
  3232.   printf ("\n");
  3233. }
  3234. #endif
  3235.  
  3236. #ifdef  TIMEONLY
  3237. main ()
  3238. {
  3239.   int itnum, i;
  3240.   long plain [2], crypt [2], cprbuf [2];
  3241.   long udiff, bitsdone, u_msec;
  3242.   unsigned ks [16] [4];
  3243.   long keyl [2];
  3244.   unsigned inkey [8];
  3245.   char  inkeyc [8]; 
  3246.  
  3247.   /* default key to NBS sample value */
  3248.   keyl [0] = 0x01234567l;
  3249.   keyl [1] = 0x89abcdefl;
  3250.   /* build key schedule (outside scanner, so default works) */
  3251.   sprdltob (keyl [0], & inkeyc [0]);
  3252.   sprdltob (keyl [1], & inkeyc [4]);
  3253.   for (i = 0; i < 8; i++) inkey [i] = (unsigned) (inkeyc [i] & 0xff);
  3254.   if (ksmake (inkey, ks) != SUCCESS)
  3255.   {
  3256.     printf ("Bad parity on key... aborting...\n");
  3257.     exit (1);
  3258.   }
  3259.  
  3260.   printf ("Enter number of test iterations [decimal]: ");
  3261.   scanf ("%d", &itnum);
  3262.  
  3263.   times (&t_before);
  3264.   for (i = 0; i < itnum; i++)   
  3265.   {
  3266.     des_encrypt (plain, crypt, ks);
  3267.     des_decrypt (crypt, cprbuf, ks);
  3268.     if ((plain [0] != cprbuf [0]) || (plain [1] != cprbuf [1]))
  3269.     {
  3270.       printf ("Encrypt and decrypt disagree -- aborting!!\n");
  3271.       exit (1);
  3272.     }
  3273.   }
  3274.   times (&t_after);
  3275.   printf ("All encryptions and decryptions verified consistent\n");
  3276.  
  3277.   /* note: the following code won't work if one times a number
  3278.      of encryptions that take less than one tick, as can occur
  3279.      on a vax with a small number of tests */
  3280.   udiff = t_after.proc_utime - t_before.proc_utime;
  3281.   printf ("user 1/60 sec ticks = %ld\n", udiff);
  3282.   bitsdone = 2 * (itnum * 64);
  3283.   u_msec = (udiff * 1000) / 60;
  3284.   printf ("%ld user msec/DES cycle\n", u_msec / ((long) 2 * itnum));
  3285.   printf ("%ld bits/user second\n", (bitsdone * 1000) / u_msec);
  3286. }
  3287. #endif
  3288.  
  3289. /* seq_nocase: */
  3290. /* perform case-insensitive comparison of null-terminated ASCII strings */
  3291. /* return 0 if not equal, 1 if equal */
  3292. /* BUG: shows a match when one string terminates as a subset of another, */
  3293. /* but this doesn't affect usability in this context */
  3294.  
  3295. int seq_nocase (str1, str2)
  3296. char *str1, *str2;
  3297. {
  3298.     char cv1, cv2;
  3299.  
  3300.     for ( ; ((*str1 != '\0') && (*str2 != '\0')); str1++, str2++)
  3301.     {
  3302.         cv1 = ((*str1 >= 'a') && (*str1 <= 'z')) ?
  3303.           (0X7F & (*str1 - ('a' - 'A'))) : *str1;
  3304.         cv2 = ((*str2 >= 'a') && (*str2 <= 'z')) ?
  3305.           (0X7F & (*str2 - ('a' - 'A'))) : *str2;
  3306.         if (cv1 != cv2)
  3307.         {       /* chars unequal */
  3308.                   return (0);
  3309.         }
  3310.     }
  3311.     /* if we get here, all characters were equal */
  3312.     return (1);
  3313. }
  3314. 
  3315. 
  3316. Received: from louie.udel.edu by huey.udel.edu id aa28026; 4 May 89 18:53 EDT
  3317. Received: from ccv.bbn.com by louie.udel.edu id aa17512; 4 May 89 18:51 EDT
  3318. Date:     Thu, 4 May 89 18:44:32 EDT
  3319. From:     Steve Kent <kent@bbn.com>
  3320. To:       Mills@udel.edu
  3321. Subject:  Re:  DES routines
  3322. Message-ID:  <8905041851.aa17512@louie.udel.edu>
  3323.  
  3324. Dave,
  3325.  
  3326.     Fell free to include it in NTP, just so long as the in-line
  3327. acknowledgement is maintained.  
  3328.  
  3329. Steve
  3330. 
  3331. P.S.  and be sure to tell all your friends ...
  3332. 
  3333.